<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.3.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/yuwanzi.io/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/yuwanzi.io/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/yuwanzi.io/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/yuwanzi.io/images/logo.svg" color="#222">

<link rel="stylesheet" href="/yuwanzi.io/css/main.css">



<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.1/css/all.min.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css">

<script class="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"suyuhuan.gitee.io","root":"/yuwanzi.io/","images":"/yuwanzi.io/images","scheme":"Muse","version":"8.2.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":false,"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"Suche...","empty":"We didn't find any results for the search: ${query}","hits_time":"${hits} results found in ${time} ms","hits":"${hits} results found"}};
  </script>
<meta name="description" content="这里是玉丸子的个人博客,与你一起发现更大的世界。">
<meta property="og:type" content="website">
<meta property="og:title" content="玉丸子 | Blog">
<meta property="og:url" content="https://suyuhuan.gitee.io/yuwanzi.io/page/7/index.html">
<meta property="og:site_name" content="玉丸子 | Blog">
<meta property="og:description" content="这里是玉丸子的个人博客,与你一起发现更大的世界。">
<meta property="og:locale">
<meta property="article:author" content="玉丸子">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="https://suyuhuan.gitee.io/yuwanzi.io/page/7/">


<script class="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh'
  };
</script>
<title>玉丸子 | Blog</title>
  




  <noscript>
  <style>
  body { margin-top: 2rem; }

  .use-motion .menu-item,
  .use-motion .sidebar,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header {
    visibility: visible;
  }

  .use-motion .header,
  .use-motion .site-brand-container .toggle,
  .use-motion .footer { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle,
  .use-motion .custom-logo-image {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line {
    transform: scaleX(1);
  }

  .search-pop-overlay, .sidebar-nav { display: none; }
  .sidebar-panel { display: block; }
  </style>
</noscript>

<link rel="alternate" href="/yuwanzi.io/atom.xml" title="玉丸子 | Blog" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="Navigationsleiste an/ausschalten" role="button">
    </div>
  </div>

  <div class="site-meta">

    <a href="/yuwanzi.io/" class="brand" rel="start">
      <i class="logo-line"></i>
      <h1 class="site-title">玉丸子 | Blog</h1>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>







</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-overview-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          Inhaltsverzeichnis
        </li>
        <li class="sidebar-nav-overview">
          Übersicht
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">玉丸子</p>
  <div class="site-description" itemprop="description">这里是玉丸子的个人博客,与你一起发现更大的世界。</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/yuwanzi.io/archives">
          <span class="site-state-item-count">68</span>
          <span class="site-state-item-name">Artikel</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/yuwanzi.io/categories/">
        <span class="site-state-item-count">39</span>
        <span class="site-state-item-name">Kategorien</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/yuwanzi.io/tags/">
        <span class="site-state-item-count">46</span>
        <span class="site-state-item-name">schlagwörter</span></a>
      </div>
  </nav>
</div>



        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner index posts-expand">

    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh">
    <link itemprop="mainEntityOfPage" href="https://suyuhuan.gitee.io/yuwanzi.io/2016/06/27/2016-06-27-redis-cluster01/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/yuwanzi.io/images/avatar.gif">
      <meta itemprop="name" content="玉丸子">
      <meta itemprop="description" content="这里是玉丸子的个人博客,与你一起发现更大的世界。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="玉丸子 | Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/yuwanzi.io/2016/06/27/2016-06-27-redis-cluster01/" class="post-title-link" itemprop="url">如何搭建与维护一个Redis集群</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Veröffentlicht am</span>

      <time title="Erstellt: 2016-06-27 18:00:00" itemprop="dateCreated datePublished" datetime="2016-06-27T18:00:00+08:00">2016-06-27</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">Bearbeitet am</span>
        <time title="Geändert am: 2020-11-07 08:58:17" itemprop="dateModified" datetime="2020-11-07T08:58:17+08:00">2020-11-07</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">in</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">后端</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Database/" itemprop="url" rel="index"><span itemprop="name">Database</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Database/Redis/" itemprop="url" rel="index"><span itemprop="name">Redis</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <p><img src="http://ww3.sinaimg.cn/mw690/63503acbjw1f67o71v3m6j20av0640st.jpg"></p>
<h3 id="Redis集群架构"><a href="#Redis集群架构" class="headerlink" title="Redis集群架构"></a>Redis集群架构</h3><p><img src="http://ww3.sinaimg.cn/mw690/63503acbjw1f67o70ppf9j20dr0fudhb.jpg"></p>
<ol>
<li><p>每一个<code>Redis</code>节点使用PING-PONG的形式互相通信。</p>
</li>
<li><p>当半数以上的节点fail时,则整个集群失效。</p>
</li>
<li><p>客户端不需要连接集群所有节点,只要连接集群中任意一个节点即可。</p>
</li>
<li><p><code>Redis</code>集群中内置了16384个哈希槽,当操作数据时,<code>Redis</code>会对key使用crc16算法算出一个结果,<br>并把结果对16384取余,每个key都会对应0-16383之间的哈希槽,<code>Redis</code>会根据节点数量平均的将<br>哈希槽映射到不同的节点上。</p>
</li>
</ol>
<h3 id="Redis投票机制"><a href="#Redis投票机制" class="headerlink" title="Redis投票机制"></a>Redis投票机制</h3><p><img src="http://ww2.sinaimg.cn/mw690/63503acbjw1f67o717oqhj20cn0acmy4.jpg"></p>
<p><code>Redis</code>集群中每一个节点都会参与投票,如果当半数以上的节点认为一个节点通信超时,则该节点fail。</p>
<p>当集群中任意节点的master(主机)挂掉,且这个节点没有slave(从机),则整个集群进入fail状态。</p>
<h3 id="搭建Redis集群"><a href="#搭建Redis集群" class="headerlink" title="搭建Redis集群"></a>搭建Redis集群</h3><h4 id="1-安装Ruby环境"><a href="#1-安装Ruby环境" class="headerlink" title="1.安装Ruby环境"></a>1.安装Ruby环境</h4><p>因为redis-trib.rb脚本依赖ruby环境,所以需要先安装ruby。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">yum install ruby </span><br><span class="line">yum install rubygems</span><br></pre></td></tr></table></figure>
<p>安装ruby和redis的接口程序</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gem install &#x2F;usr&#x2F;local&#x2F;redis-3.0.0.gem</span><br></pre></td></tr></table></figure>
<h4 id="2-搭建Redis集群"><a href="#2-搭建Redis集群" class="headerlink" title="2.搭建Redis集群"></a>2.搭建Redis集群</h4><p>一个<code>Redis</code>集群最少需要3组主从机,即6个<code>Redis</code>。</p>
<p><img src="http://ww3.sinaimg.cn/mw690/63503acbjw1f67o71g231j20cz03lta6.jpg"></p>
<p>修改redis.conf配置文件,将集群开关开启。</p>
<p><img src="http://ww2.sinaimg.cn/mw690/63503acbjw1f67obgv67nj20an07gdim.jpg"></p>
<p>启动<code>Redis</code>实例</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">cd redis01</span><br><span class="line">.&#x2F;redis-server redis.conf</span><br><span class="line">cd ..</span><br><span class="line">cd redis02</span><br><span class="line">.&#x2F;redis-server redis.conf</span><br><span class="line">cd ..</span><br><span class="line">cd redis03</span><br><span class="line">.&#x2F;redis-server redis.conf</span><br><span class="line">cd ..</span><br><span class="line">cd redis04</span><br><span class="line">.&#x2F;redis-server redis.conf</span><br><span class="line">cd ..</span><br><span class="line">cd redis05</span><br><span class="line">.&#x2F;redis-server redis.conf</span><br><span class="line">cd ..</span><br><span class="line">cd redis06</span><br><span class="line">.&#x2F;redis-server redis.conf</span><br><span class="line">cd ..</span><br></pre></td></tr></table></figure>
<p>使用redis-trib.rb创建集群</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.&#x2F;redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005  127.0.0.1:7006</span><br></pre></td></tr></table></figure>
<h4 id="3-添加主节点"><a href="#3-添加主节点" class="headerlink" title="3.添加主节点"></a>3.添加主节点</h4><p>如果想添加一个port为7007的<code>Redis</code>实例,可以使用以下命令。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.&#x2F;redis-trib.rb add-node 127.0.0.1:7007 127.0.0.1:7001</span><br></pre></td></tr></table></figure>
<p>当添加了一个主节点后,需要重新分配哈希槽。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.&#x2F;redis-trib.rb reshard 127.0.0.1:7001</span><br></pre></td></tr></table></figure>
<h4 id="4-添加从节点"><a href="#4-添加从节点" class="headerlink" title="4.添加从节点"></a>4.添加从节点</h4><p>添加一个port为7008的<code>Redis</code>实例做为7007的从节点。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.&#x2F;redis-trib.rb add-node --slave --master-id cad9f7413ec6842c971dbcc2c48b4ca959eb5db4  127.0.0.1:7008 127.0.0.1:7001</span><br></pre></td></tr></table></figure>
<p>命令格式: ./redis-trib.rb add-node –slave –master-id 主节点id 新加从节点的ip和端口 集群中节点的ip和端口(任意一个节点)。</p>
<p>主节点id可以在client中使用 <strong>cluster nodes</strong> 命令查询。</p>
<p>注意: 如果原来该结点在集群中的配置信息已经生成到cluster-config-file指定的配置文件中（如果cluster-config-file没有指定则默认为nodes.conf),则会报错:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[ERR] Node XXXXXX is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0</span><br></pre></td></tr></table></figure>
<p>解决方法: 删除生成的配置文件 nodes.conf,再执行./redis-trib.rb add-node命令。</p>
<h4 id="5-删除节点"><a href="#5-删除节点" class="headerlink" title="5.删除节点"></a>5.删除节点</h4><p>./redis-trib.rb del-node 要删除的节点的ip和端口 节点id<br>注意: 如果这个节点已经占有哈希槽,则无法删除,需要先将哈希槽分配出去。</p>
<h3 id="Jedis连接集群"><a href="#Jedis连接集群" class="headerlink" title="Jedis连接集群"></a>Jedis连接集群</h3><p>使用Jedis连接集群需要先创建JedisCluster对象。代码如下:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test01</span><span class="params">()</span></span>&#123;</span><br><span class="line">	Set&lt;HostAndPort&gt; nodes = <span class="keyword">new</span> HashSet&lt;HostAndPort&gt;();</span><br><span class="line">	nodes.add(<span class="keyword">new</span> HostAndPort(<span class="string">&quot;192.168.145.134&quot;</span>, <span class="number">7001</span>));</span><br><span class="line">	nodes.add(<span class="keyword">new</span> HostAndPort(<span class="string">&quot;192.168.145.134&quot;</span>, <span class="number">7002</span>));</span><br><span class="line">	nodes.add(<span class="keyword">new</span> HostAndPort(<span class="string">&quot;192.168.145.134&quot;</span>, <span class="number">7003</span>));</span><br><span class="line">	nodes.add(<span class="keyword">new</span> HostAndPort(<span class="string">&quot;192.168.145.134&quot;</span>, <span class="number">7004</span>));</span><br><span class="line">	nodes.add(<span class="keyword">new</span> HostAndPort(<span class="string">&quot;192.168.145.134&quot;</span>, <span class="number">7005</span>));</span><br><span class="line">	nodes.add(<span class="keyword">new</span> HostAndPort(<span class="string">&quot;192.168.145.134&quot;</span>, <span class="number">7006</span>));</span><br><span class="line">	<span class="comment">// 创建JedisCluster</span></span><br><span class="line">	JedisCluster jedisCluster = <span class="keyword">new</span> JedisCluster(nodes);</span><br><span class="line">	<span class="comment">// 操作redis</span></span><br><span class="line">	String set = jedisCluster.set(<span class="string">&quot;hello&quot;</span>, <span class="string">&quot;helloWorld&quot;</span>);</span><br><span class="line">	String hello = jedisCluster.get(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">	System.out.println(set);</span><br><span class="line">	System.out.println(hello);</span><br><span class="line">	<span class="comment">// 关闭JedisCluster</span></span><br><span class="line">	jedisCluster.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在Spring容器中维护:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">   &lt;bean class&#x3D;&quot;redis.clients.jedis.JedisCluster&quot;&gt;</span><br><span class="line">	&lt;constructor-arg name&#x3D;&quot;nodes&quot;&gt;</span><br><span class="line">		&lt;set&gt;</span><br><span class="line">			&lt;bean class&#x3D;&quot;redis.clients.jedis.HostAndPort&quot;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;host&quot; value&#x3D;&quot;192.168.145.134&quot;&#x2F;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;port&quot; value&#x3D;&quot;7001&quot;&#x2F;&gt;</span><br><span class="line">			&lt;&#x2F;bean&gt;</span><br><span class="line">			&lt;bean class&#x3D;&quot;redis.clients.jedis.HostAndPort&quot;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;host&quot; value&#x3D;&quot;192.168.145.134&quot;&#x2F;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;port&quot; value&#x3D;&quot;7002&quot;&#x2F;&gt;</span><br><span class="line">			&lt;&#x2F;bean&gt;</span><br><span class="line">			&lt;bean class&#x3D;&quot;redis.clients.jedis.HostAndPort&quot;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;host&quot; value&#x3D;&quot;192.168.145.134&quot;&#x2F;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;port&quot; value&#x3D;&quot;7003&quot;&#x2F;&gt;</span><br><span class="line">			&lt;&#x2F;bean&gt;</span><br><span class="line">			&lt;bean class&#x3D;&quot;redis.clients.jedis.HostAndPort&quot;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;host&quot; value&#x3D;&quot;192.168.145.134&quot;&#x2F;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;port&quot; value&#x3D;&quot;7004&quot;&#x2F;&gt;</span><br><span class="line">			&lt;&#x2F;bean&gt;</span><br><span class="line">			&lt;bean class&#x3D;&quot;redis.clients.jedis.HostAndPort&quot;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;host&quot; value&#x3D;&quot;192.168.145.134&quot;&#x2F;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;port&quot; value&#x3D;&quot;7005&quot;&#x2F;&gt;</span><br><span class="line">			&lt;&#x2F;bean&gt;</span><br><span class="line">			&lt;bean class&#x3D;&quot;redis.clients.jedis.HostAndPort&quot;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;host&quot; value&#x3D;&quot;192.168.145.134&quot;&#x2F;&gt;</span><br><span class="line">				&lt;constructor-arg name&#x3D;&quot;port&quot; value&#x3D;&quot;7006&quot;&#x2F;&gt;</span><br><span class="line">			&lt;&#x2F;bean&gt;</span><br><span class="line">		&lt;&#x2F;set&gt;</span><br><span class="line">	&lt;&#x2F;constructor-arg&gt;</span><br><span class="line">&lt;&#x2F;bean&gt;</span><br></pre></td></tr></table></figure>
      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh">
    <link itemprop="mainEntityOfPage" href="https://suyuhuan.gitee.io/yuwanzi.io/2016/06/24/2016-06-24-nginx-initiation/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/yuwanzi.io/images/avatar.gif">
      <meta itemprop="name" content="玉丸子">
      <meta itemprop="description" content="这里是玉丸子的个人博客,与你一起发现更大的世界。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="玉丸子 | Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/yuwanzi.io/2016/06/24/2016-06-24-nginx-initiation/" class="post-title-link" itemprop="url">如何安装与搭建一个Nginx服务器</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Veröffentlicht am</span>

      <time title="Erstellt: 2016-06-24 18:00:00" itemprop="dateCreated datePublished" datetime="2016-06-24T18:00:00+08:00">2016-06-24</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">Bearbeitet am</span>
        <time title="Geändert am: 2020-11-07 08:58:17" itemprop="dateModified" datetime="2020-11-07T08:58:17+08:00">2020-11-07</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">in</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">后端</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/" itemprop="url" rel="index"><span itemprop="name">负载均衡</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/Nginx/" itemprop="url" rel="index"><span itemprop="name">Nginx</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <p><img src="http://ww2.sinaimg.cn/mw690/63503acbjw1f67nyh9gq7j20cp075wel.jpg"></p>
<h3 id="Nginx介绍"><a href="#Nginx介绍" class="headerlink" title="Nginx介绍"></a>Nginx介绍</h3><p><code>Nginx</code>是一款轻量级的Web 服务器/反向代理服务器及电子邮件（IMAP/POP3）代理服务器，并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev所开发，供俄国大型的入口网站及搜索引擎Rambler使用。</p>
<h3 id="Nginx应用场景"><a href="#Nginx应用场景" class="headerlink" title="Nginx应用场景"></a>Nginx应用场景</h3><ol>
<li>作为http服务器使用并独立提供http服务。</li>
<li>虚拟主机。</li>
<li>用于反向代理与负载均衡,当并发量非常大时,可以使用<code>Nginx</code>对服务器集群进行反向代理与负载均衡,提高吞吐量。</li>
</ol>
<h3 id="反向代理"><a href="#反向代理" class="headerlink" title="反向代理"></a>反向代理</h3><p><img src="http://ww1.sinaimg.cn/mw690/63503acbjw1f67nz4ekjmj20tq0eqgmx.jpg"></p>
<p>反向代理是指以代理服务器来接受internet上的连接请求，然后将请求转发给内部网络上的服务器，并将从服务器上得到的结果返回给internet上请求连接的客户端，此时代理服务器对外就表现为一个反向代理服务器。</p>
<h3 id="Nginx安装流程"><a href="#Nginx安装流程" class="headerlink" title="Nginx安装流程"></a>Nginx安装流程</h3><ol>
<li><p>Nginx依赖于以下4个库</p>
<ul>
<li><p>gcc<br>  安装nginx需要先将官网下载的源码进行编译，编译依赖gcc环境</p>
<pre><code>**yum install gcc-c++**</code></pre>
</li>
<li><p>pcre<br>  PCRE(Perl Compatible Regular Expressions)是一个Perl库，包括 perl 兼容的正则表达式库。nginx的http模块使用pcre来解析正则表达式，所以需要在linux上安装pcre库。<br>   <strong>yum install -y pcre pcre-devel</strong></p>
</li>
<li><p>zlib<br>  zlib库提供了很多种压缩和解压缩的方式，nginx使用zlib对http包的内容进行gzip，所以需要在linux上安装zlib库。<br>   <strong>yum install -y zlib zlib-devel</strong></p>
</li>
<li><p>openssl<br>  OpenSSL 是一个强大的安全套接字层密码库，囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议，并提供丰富的应用程序供测试或其它目的使用。<br>nginx不仅支持http协议，还支持https（即在ssl协议上传输http），所以需要在linux安装openssl库。<br>  <strong>yum install -y openssl openssl-devel</strong></p>
</li>
<li><p>一键安装依赖包 <strong>yum -y install zlib zlib-devel openssl openssl–devel pcre pcre-devel</strong>     </p>
</li>
</ul>
</li>
<li><p>解压Nginx源码包  </p>
</li>
<li><p>使用configure创建makefile</p>
</li>
</ol>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">.&#x2F;configure \</span><br><span class="line">--prefix&#x3D;&#x2F;usr&#x2F;local&#x2F;nginx \</span><br><span class="line">--pid-path&#x3D;&#x2F;var&#x2F;run&#x2F;nginx&#x2F;nginx.pid \</span><br><span class="line">--lock-path&#x3D;&#x2F;var&#x2F;lock&#x2F;nginx.lock \</span><br><span class="line">--error-log-path&#x3D;&#x2F;var&#x2F;log&#x2F;nginx&#x2F;error.log \</span><br><span class="line">--http-log-path&#x3D;&#x2F;var&#x2F;log&#x2F;nginx&#x2F;access.log \</span><br><span class="line">--with-http_gzip_static_module \</span><br><span class="line">--http-client-body-temp-path&#x3D;&#x2F;var&#x2F;temp&#x2F;nginx&#x2F;client \</span><br><span class="line">--http-proxy-temp-path&#x3D;&#x2F;var&#x2F;temp&#x2F;nginx&#x2F;proxy \</span><br><span class="line">--http-fastcgi-temp-path&#x3D;&#x2F;var&#x2F;temp&#x2F;nginx&#x2F;fastcgi \</span><br><span class="line">--http-uwsgi-temp-path&#x3D;&#x2F;var&#x2F;temp&#x2F;nginx&#x2F;uwsgi \</span><br><span class="line">--http-scgi-temp-path&#x3D;&#x2F;var&#x2F;temp&#x2F;nginx&#x2F;scgi</span><br></pre></td></tr></table></figure>
<ol start="4">
<li><p>make &amp; make install</p>
</li>
<li><p>cd /usr/local/nginx/sbin 目录 </p>
<ul>
<li><p><strong>./nginx</strong> 开启<code>Nginx</code></p>
</li>
<li><p><strong>./nginx -s stop</strong> 关闭<code>Nginx</code></p>
</li>
<li><p><strong>./nginx -s reload</strong> 重新加载<code>Nginx</code>配置文件</p>
</li>
</ul>
</li>
</ol>
<h3 id="Nginx配置文件"><a href="#Nginx配置文件" class="headerlink" title="Nginx配置文件"></a>Nginx配置文件</h3><p><img src="http://ww4.sinaimg.cn/mw690/63503acbjw1f67o1jecrjj20ic0jwdj6.jpg"></p>
<p>nginx.conf是<code>Nginx</code>的主要配置文件,它的主要结构如下</p>
<ul>
<li><p>worker_process表示工作进程的数量，一般设置为cpu的核数</p>
</li>
<li><p>worker_connections表示每个工作进程的最大连接数</p>
</li>
<li><p>server{} 定义了一个虚拟机,如果要添加一个虚拟机,则添加一个server{}即可。</p>
<ul>
<li><p>listen监听的端口</p>
</li>
<li><p>server_name监听的域名</p>
</li>
<li><p>location{}配置匹配的URI</p>
<ul>
<li><p>root 指定URI查找的资源路径,为相对路径。</p>
</li>
<li><p>index 指定首页的名称,可以配置多个。</p>
</li>
<li><p>proxy_pass 指定反向代理转发的路径。</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="Nginx配置负载均衡"><a href="#Nginx配置负载均衡" class="headerlink" title="Nginx配置负载均衡"></a>Nginx配置负载均衡</h3><p><img src="http://ww4.sinaimg.cn/mw690/63503acbjw1f67o1j87tcj20cf08pq44.jpg"></p>
<p>对upstream test{}中的2个web服务器配置了负载均衡,weight设置权值,权值越高的服务器承载的压力就越大。</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh">
    <link itemprop="mainEntityOfPage" href="https://suyuhuan.gitee.io/yuwanzi.io/2016/06/19/2016-06-19-lucene/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/yuwanzi.io/images/avatar.gif">
      <meta itemprop="name" content="玉丸子">
      <meta itemprop="description" content="这里是玉丸子的个人博客,与你一起发现更大的世界。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="玉丸子 | Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/yuwanzi.io/2016/06/19/2016-06-19-lucene/" class="post-title-link" itemprop="url">使用Lucene实现全文检索</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Veröffentlicht am</span>

      <time title="Erstellt: 2016-06-19 00:00:00" itemprop="dateCreated datePublished" datetime="2016-06-19T00:00:00+08:00">2016-06-19</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">Bearbeitet am</span>
        <time title="Geändert am: 2020-11-07 08:58:17" itemprop="dateModified" datetime="2020-11-07T08:58:17+08:00">2020-11-07</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">in</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">后端</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/%E5%85%A8%E6%96%87%E6%A3%80%E7%B4%A2/" itemprop="url" rel="index"><span itemprop="name">全文检索</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/%E5%85%A8%E6%96%87%E6%A3%80%E7%B4%A2/Lucene/" itemprop="url" rel="index"><span itemprop="name">Lucene</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h3 id="1-Lucene介绍"><a href="#1-Lucene介绍" class="headerlink" title="1. Lucene介绍"></a>1. Lucene介绍</h3><p> Lucene是apache下的一个开源的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎（英文与德文两种西方语言）。<br>它为软件开发人员提供一个简单易用的工具包（类库）,以方便的在目标系统中实现全文检索的功能。</p>
<h4 id="全文检索"><a href="#全文检索" class="headerlink" title="全文检索"></a>全文检索</h4><p> 全文检索首先将要查询的目标文档中的词提取出来，组成索引，通过查询索引达到搜索目标文档的目的。这种先建立索引，再对索引进行搜索的过程就叫全文检索（Full-text Search）。</p>
<h4 id="Lucene的优点"><a href="#Lucene的优点" class="headerlink" title="Lucene的优点"></a>Lucene的优点</h4><ol>
<li>索引文件格式独立于应用平台。Lucene定义了一套以8位字节为基础的索引文件格式，使得兼容系统或者不同平台的应用能够共享建立的索引文件。</li>
<li>在传统全文检索引擎的倒排索引的基础上，实现了分块索引，能够针对新的文件建立小文件索引，提升索引速度。然后通过与原有索引的合并，达到优化的目的。</li>
<li>优秀的面向对象的系统架构，使得对于Lucene扩展的学习难度降低，方便扩充新功能。</li>
<li>设计了独立于语言和文件格式的文本分析接口，索引器通过接受Token流完成索引文件的创立，用户扩展新的语言和文件格式，只需要实现文本分析的接口。</li>
<li>已经默认实现了一套强大的查询引擎，用户无需自己编写代码即可使系统可获得强大的查询能力，Lucene的查询实现中默认实现了布尔操作、模糊查询（Fuzzy Search[11]）、分组查询等等。</li>
</ol>
<h3 id="2-Lucene检索流程"><a href="#2-Lucene检索流程" class="headerlink" title="2. Lucene检索流程"></a>2. Lucene检索流程</h3><p><img src="http://ww2.sinaimg.cn/mw690/63503acbjw1f67nt0n317j20o60l80u0.jpg"></p>
<ul>
<li>创建索引流程:Gather Data(采集数据) –&gt; 构造文档对象 –&gt; 分词 –&gt; 创建索引并存入索引库</li>
<li>搜索流程:用户发起搜索请求 –&gt; 创建查询对象 –&gt; 从索引库中搜索 –&gt; 渲染并返回搜索结果</li>
</ul>
<h3 id="3-索引的逻辑结构"><a href="#3-索引的逻辑结构" class="headerlink" title="3. 索引的逻辑结构"></a>3. 索引的逻辑结构</h3><ul>
<li>一个非结构化的数据统一格式为<code>document</code>文档,一个<code>document</code>可以有多个<code>field</code>。</li>
<li>当用户搜索时,Lucene会从索引域中搜索,并找到对应的<code>document</code>,将<code>document</code>中的<code>filed</code>进行分词,然后根据分词创建索引。</li>
</ul>
<h3 id="4-创建索引"><a href="#4-创建索引" class="headerlink" title="4. 创建索引"></a>4. 创建索引</h3><h4 id="创建索引的流程"><a href="#创建索引的流程" class="headerlink" title="创建索引的流程"></a>创建索引的流程</h4><p><img src="http://ww1.sinaimg.cn/mw690/63503acbjw1f67nv272uaj20ag0fumxd.jpg"></p>
<ol>
<li>IndexWriter是核心对象,它可以完成创建索引、更新索引、删除索引等操作。</li>
<li>Directory负责对索引进行存储,它是一个抽象类,子类为FSDirectory(文件中存储)、RAMDirectory(内存中存储)</li>
</ol>
<h4 id="创建索引"><a href="#创建索引" class="headerlink" title="创建索引"></a>创建索引</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">createIndex</span><span class="params">()</span> </span>&#123;</span><br><span class="line">	<span class="comment">// 获得原始数据</span></span><br><span class="line">	ItemsDao itemsDao = <span class="keyword">new</span> ItemsDaoImpl();</span><br><span class="line">	List&lt;Items&gt; items = itemsDao.findAllItems();</span><br><span class="line">	<span class="comment">// 创建Document</span></span><br><span class="line">	List&lt;Document&gt; documents = <span class="keyword">new</span> ArrayList&lt;Document&gt;();</span><br><span class="line">	Document document = <span class="keyword">null</span>;</span><br><span class="line">	<span class="comment">// 遍历原始数据并封装到field</span></span><br><span class="line">	<span class="keyword">for</span> (Items item : items) &#123;</span><br><span class="line">		document = <span class="keyword">new</span> Document();</span><br><span class="line">		<span class="comment">/**</span></span><br><span class="line"><span class="comment">		 * 参数1:field的域名 参数2:要封装的数据 参数3:是否存储</span></span><br><span class="line"><span class="comment">		 */</span></span><br><span class="line">		Field name = <span class="keyword">new</span> TextField(<span class="string">&quot;name&quot;</span>, item.getName(), Store.YES);</span><br><span class="line">		Field id = <span class="keyword">new</span> StringField(<span class="string">&quot;id&quot;</span>, item.getId().toString(), Store.YES);</span><br><span class="line">		Field price = <span class="keyword">new</span> TextField(<span class="string">&quot;price&quot;</span>, item.getPrice().toString(), Store.YES);</span><br><span class="line">		<span class="comment">// 将field封装到document</span></span><br><span class="line">		document.add(name);</span><br><span class="line">		document.add(id);</span><br><span class="line">		document.add(price);</span><br><span class="line"></span><br><span class="line">		documents.add(document);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="comment">// 创建一个标准分析器</span></span><br><span class="line">	Analyzer analyzer = <span class="keyword">new</span> StandardAnalyzer();</span><br><span class="line">	<span class="comment">// 索引库目录</span></span><br><span class="line">	Directory directory = FSDirectory.open(<span class="keyword">new</span> File(<span class="string">&quot;D:\\Repository\\indexDatabase\\test&quot;</span>));</span><br><span class="line">	<span class="comment">// 创建IndexWriterConfig</span></span><br><span class="line">	IndexWriterConfig indexWriterConfig = <span class="keyword">new</span> IndexWriterConfig(analyzer);</span><br><span class="line">	IndexWriter indexWriter = <span class="keyword">null</span>;</span><br><span class="line">	<span class="keyword">try</span> &#123;</span><br><span class="line">		<span class="comment">// 创建IndexWriter</span></span><br><span class="line">		indexWriter = <span class="keyword">new</span> IndexWriter(directory, indexWriterConfig);</span><br><span class="line">		<span class="keyword">for</span> (Document doc : documents) &#123;</span><br><span class="line">			indexWriter.addDocument(doc);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">		e.printStackTrace();</span><br><span class="line">	&#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">		<span class="comment">// 关闭IndexWriter</span></span><br><span class="line">		indexWriter.close();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="5-搜索索引"><a href="#5-搜索索引" class="headerlink" title="5. 搜索索引"></a>5. 搜索索引</h3><h4 id="使用QueryParse"><a href="#使用QueryParse" class="headerlink" title="使用QueryParse"></a>使用QueryParse</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">searchIndex</span><span class="params">()</span> <span class="keyword">throws</span> ParseException </span>&#123;</span><br><span class="line">	<span class="comment">// 创建标准分析器</span></span><br><span class="line">	Analyzer analyzer = <span class="keyword">new</span> StandardAnalyzer();</span><br><span class="line">	<span class="comment">// 创建QueryParser,c</span></span><br><span class="line">	<span class="comment">// 参数1:Field域名 参数2:分析器</span></span><br><span class="line">	QueryParser queryParser = <span class="keyword">new</span> QueryParser(<span class="string">&quot;name&quot;</span>, analyzer);</span><br><span class="line">	<span class="comment">// 创建Query 查找name为冰箱的</span></span><br><span class="line">	Query query = queryParser.parse(<span class="string">&quot;name:冰箱&quot;</span>);</span><br><span class="line">	<span class="comment">// 索引库目录</span></span><br><span class="line">	Directory directory = FSDirectory.open(<span class="keyword">new</span> File(<span class="string">&quot;D:\\Repository\\indexDatabase\\test&quot;</span>));</span><br><span class="line">	IndexReader indexReader = <span class="keyword">null</span>;</span><br><span class="line">	<span class="keyword">try</span> &#123;</span><br><span class="line">		<span class="comment">// 创建IndexReader</span></span><br><span class="line">		indexReader = DirectoryReader.open(directory);</span><br><span class="line">		<span class="comment">// 创建IndexSearcher</span></span><br><span class="line">		IndexSearcher indexSearcher = <span class="keyword">new</span> IndexSearcher(indexReader);</span><br><span class="line">		<span class="comment">// 执行搜索,并返回TopDoc对象 参数1:query对象 参数2:最大记录数</span></span><br><span class="line">		TopDocs topDocs = indexSearcher.search(query, <span class="number">10</span>);</span><br><span class="line">		<span class="comment">// 获得TopDocs中的记录对象</span></span><br><span class="line">		ScoreDoc[] scoreDocs = topDocs.scoreDocs;</span><br><span class="line">		<span class="keyword">for</span> (ScoreDoc scoreDoc : scoreDocs) &#123;</span><br><span class="line">			<span class="comment">// 获得doc的ID</span></span><br><span class="line">			<span class="keyword">int</span> docId = scoreDoc.doc;</span><br><span class="line">			<span class="comment">// 根据id查找到doc</span></span><br><span class="line">			Document doc = indexSearcher.doc(docId);</span><br><span class="line">			<span class="comment">// 打印数据</span></span><br><span class="line">			System.out.println(<span class="string">&quot;商品名: &quot;</span> + doc.get(<span class="string">&quot;name&quot;</span>));</span><br><span class="line">			System.out.println(<span class="string">&quot;价格: &quot;</span> + doc.get(<span class="string">&quot;price&quot;</span>));</span><br><span class="line">		&#125;</span><br><span class="line">	&#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">		e.printStackTrace();</span><br><span class="line">	&#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">		<span class="comment">// 关闭reader</span></span><br><span class="line">		indexReader.close();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="使用Query的子类"><a href="#使用Query的子类" class="headerlink" title="使用Query的子类"></a>使用Query的子类</h4><p><strong>TermQuery</strong></p>
<p>TermQuery使用搜索关键词进行查询。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">searcher</span><span class="params">(Query query)</span> </span>&#123;</span><br><span class="line">	<span class="comment">// 索引库</span></span><br><span class="line">	Directory directory = FSDirectory.open(<span class="keyword">new</span> File(<span class="string">&quot;D:\\Repository\\indexDatabase\\test&quot;</span>));</span><br><span class="line">	<span class="comment">// IndexReader</span></span><br><span class="line">	IndexReader reader = <span class="keyword">null</span>;</span><br><span class="line">	<span class="keyword">try</span> &#123;</span><br><span class="line">		reader = DirectoryReader.open(directory);</span><br><span class="line">		<span class="comment">// IndexSearcher</span></span><br><span class="line">		IndexSearcher searcher = <span class="keyword">new</span> IndexSearcher(reader);</span><br><span class="line">		TopDocs topDocs = searcher.search(query, <span class="number">10</span>);</span><br><span class="line">		ScoreDoc[] scoreDocs = topDocs.scoreDocs;</span><br><span class="line">		<span class="keyword">for</span> (ScoreDoc scoreDoc : scoreDocs) &#123;</span><br><span class="line">			<span class="keyword">int</span> docId = scoreDoc.doc;</span><br><span class="line">			Document document = searcher.doc(docId);</span><br><span class="line">			System.out.println(<span class="string">&quot;商品id :&quot;</span> + document.get(<span class="string">&quot;id&quot;</span>));</span><br><span class="line">			System.out.println(<span class="string">&quot;商品名称 :&quot;</span> + document.get(<span class="string">&quot;name&quot;</span>));</span><br><span class="line">			System.out.println(<span class="string">&quot;商品价格 :&quot;</span> + document.get(<span class="string">&quot;price&quot;</span>));</span><br><span class="line">		&#125;</span><br><span class="line">	&#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">		e.printStackTrace();</span><br><span class="line">	&#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">		reader.close();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">termQuery</span><span class="params">()</span> </span>&#123;</span><br><span class="line">	<span class="comment">// 创建TermQuery 查询name中有冰箱的 等效于 name:冰箱</span></span><br><span class="line">	Query query = <span class="keyword">new</span> TermQuery(<span class="keyword">new</span> Term(<span class="string">&quot;name&quot;</span>, <span class="string">&quot;冰箱&quot;</span>));</span><br><span class="line">	searcher(query);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>NumericRangeQuery</strong></p>
<p>数字范围查询</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">numericRangeQuery</span><span class="params">()</span></span>&#123;</span><br><span class="line">	<span class="comment">// 创建查询</span></span><br><span class="line">	<span class="comment">// 第一个参数：域名</span></span><br><span class="line">	<span class="comment">// 第二个参数：最小值</span></span><br><span class="line">	<span class="comment">// 第三个参数：最大值</span></span><br><span class="line">	<span class="comment">// 第四个参数：是否包含最小值</span></span><br><span class="line">	<span class="comment">// 第五个参数：是否包含最大值</span></span><br><span class="line">	Query query = NumericRangeQuery.newLongRange(<span class="string">&quot;price&quot;</span>, l00, <span class="number">1000</span>, <span class="keyword">true</span>,<span class="keyword">true</span>);</span><br><span class="line">	<span class="comment">// 2、 执行搜索</span></span><br><span class="line">	searcher(query);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>BooleanQuery</strong></p>
<p>布尔查询,用于组合条件查询。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">   <span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">booleanQuery</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">	BooleanQuery query = <span class="keyword">new</span> BooleanQuery();</span><br><span class="line">	Query query1 = <span class="keyword">new</span> TermQuery(<span class="keyword">new</span> Term(<span class="string">&quot;id&quot;</span>, <span class="string">&quot;3&quot;</span>));</span><br><span class="line">	Query query2 = NumericRangeQuery.newFloatRange(<span class="string">&quot;price&quot;</span>, <span class="number">10f</span>, <span class="number">200f</span>,</span><br><span class="line">			<span class="keyword">true</span>, <span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">	<span class="comment">//MUST：查询条件必须满足，相当于AND</span></span><br><span class="line">	<span class="comment">//SHOULD:查询条件可选，相当于OR</span></span><br><span class="line">	<span class="comment">//MUST_NOT：查询条件不能满足，相当于NOT非</span></span><br><span class="line">	query.add(query1, Occur.MUST);</span><br><span class="line">	query.add(query2, Occur.SHOULD);</span><br><span class="line">	</span><br><span class="line">	System.out.println(query);</span><br><span class="line"></span><br><span class="line">	searcher(query);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ol>
<li>MUST和MUST表示“与”的关系，即“交集”。 </li>
<li>MUST和MUST_NOT前者包含后者不包含。</li>
<li>MUST_NOT和MUST_NOT没有结果,没有意义。</li>
<li>SHOULD与MUST表示MUST，SHOULD失去意义。</li>
<li>SHOUlD与MUST_NOT相当于MUST与MUST_NOT。</li>
<li>SHOULD与SHOULD表示“或”的概念。</li>
</ol>
<h3 id="6-删除索引"><a href="#6-删除索引" class="headerlink" title="6. 删除索引"></a>6. 删除索引</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">deleteIndex</span><span class="params">()</span></span>&#123;</span><br><span class="line">		<span class="comment">// 指定索引库</span></span><br><span class="line">		Directory directory = FSDirectory.open(<span class="keyword">new</span> File(<span class="string">&quot;D:\\Repository\\indexDatabase\\test&quot;</span>));</span><br><span class="line">		<span class="comment">// 创建IndexWriterConfig</span></span><br><span class="line">		IndexWriterConfig indexWriterConfig = <span class="keyword">new</span> IndexWriterConfig(<span class="keyword">new</span> StandardAnalyzer());</span><br><span class="line">		<span class="comment">// 创建IndexWriter</span></span><br><span class="line">		IndexWriter indexWriter = <span class="keyword">new</span> IndexWriter(directory, indexWriterConfig);</span><br><span class="line">		<span class="comment">// 删除指定的索引</span></span><br><span class="line">		indexWriter.deleteDocuments(<span class="keyword">new</span> Term(<span class="string">&quot;name&quot;</span>,<span class="string">&quot;冰箱&quot;</span>));</span><br><span class="line">		<span class="comment">// 关闭indexWriter</span></span><br><span class="line">		indexWriter.close();</span><br><span class="line">	&#125;</span><br></pre></td></tr></table></figure>
<h3 id="7-修改索引"><a href="#7-修改索引" class="headerlink" title="7. 修改索引"></a>7. 修改索引</h3><p>在Lucene中修改索引即是替换索引,先将原来的索引删除,再保存新的索引。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">modifyIndex</span><span class="params">()</span> </span>&#123;</span><br><span class="line">	<span class="comment">// 指定索引库</span></span><br><span class="line">	Directory directory = FSDirectory.open(<span class="keyword">new</span> File(<span class="string">&quot;D:\\Repository\\indexDatabase\\test&quot;</span>));</span><br><span class="line">	<span class="comment">// IndexWriterConfig</span></span><br><span class="line">	IndexWriterConfig indexWriterConfig = <span class="keyword">new</span> IndexWriterConfig(<span class="keyword">new</span> StandardAnalyzer());</span><br><span class="line">	<span class="comment">// IndexWriter</span></span><br><span class="line">	IndexWriter indexWriter = <span class="keyword">new</span> IndexWriter(directory, indexWriterConfig);</span><br><span class="line">	<span class="comment">// 创建一个Document</span></span><br><span class="line">	Document document = <span class="keyword">new</span> Document();</span><br><span class="line">	Field name = <span class="keyword">new</span> TextField(<span class="string">&quot;name&quot;</span>, <span class="string">&quot;比利海灵顿&quot;</span>, Store.YES);</span><br><span class="line">	document.add(name);</span><br><span class="line">	<span class="comment">// 修改索引</span></span><br><span class="line">	indexWriter.updateDocument(<span class="keyword">new</span> Term(<span class="string">&quot;name&quot;</span>, <span class="string">&quot;冰箱&quot;</span>), document);</span><br><span class="line">	indexWriter.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="8-相关度排序"><a href="#8-相关度排序" class="headerlink" title="8. 相关度排序"></a>8. 相关度排序</h3><p>Lucene通过计算Term的权重,对查询关键字和索引文档的相关度进行打分,分越高的就排在越前面。</p>
<p>影响Term的权重有两个因素:</p>
<ul>
<li>Term Frequency:Term在文档中的出现频率,次数越多,则代表这个Term对该文档越重要,即权重越高。</li>
<li>Document Frequency:指多少文档包含这个Term的频率,频率越高,则代表这个Term越不重要,即权重越低。</li>
</ul>
<h4 id="手动设置权值"><a href="#手动设置权值" class="headerlink" title="手动设置权值"></a>手动设置权值</h4><p><strong>在创建索引时设置权值</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">  <span class="keyword">for</span> (Items item : items) &#123;</span><br><span class="line">	document = <span class="keyword">new</span> Document();</span><br><span class="line">	<span class="comment">/**</span></span><br><span class="line"><span class="comment">	 * 参数1:field的域名 参数2:要封装的数据 参数3:是否存储</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	Field name = <span class="keyword">new</span> TextField(<span class="string">&quot;name&quot;</span>, item.getName(), Store.YES);</span><br><span class="line">	Field id = <span class="keyword">new</span> StringField(<span class="string">&quot;id&quot;</span>, item.getId().toString(), Store.YES);</span><br><span class="line">	Field price = <span class="keyword">new</span> TextField(<span class="string">&quot;price&quot;</span>, item.getPrice().toString(), Store.YES);</span><br><span class="line">	<span class="comment">// 给name域增加权值</span></span><br><span class="line">	name.setBoost(<span class="number">100f</span>);</span><br><span class="line">	<span class="comment">// 将field封装到document</span></span><br><span class="line">	document.add(name);</span><br><span class="line">	document.add(id);</span><br><span class="line">	document.add(price);</span><br><span class="line"></span><br><span class="line">	documents.add(document);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>在搜索时设置权值</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setBoosts</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">		<span class="comment">// 搜索的域名数组</span></span><br><span class="line">		String[] fields = &#123; <span class="string">&quot;name&quot;</span>, <span class="string">&quot;price&quot;</span> &#125;;</span><br><span class="line">		<span class="comment">// 设置权值</span></span><br><span class="line">		Map&lt;String, Float&gt; boosts = <span class="keyword">new</span> HashMap&lt;String, Float&gt;();</span><br><span class="line">		<span class="comment">// 给name域设置权重</span></span><br><span class="line">		boosts.put(<span class="string">&quot;name&quot;</span>, <span class="number">100f</span>);</span><br><span class="line">		<span class="comment">// 创建MultiFieldQueryParse</span></span><br><span class="line">		MultiFieldQueryParser multiFieldQueryParser = <span class="keyword">new</span> MultiFieldQueryParser(fields, <span class="keyword">new</span> StandardAnalyzer(), boosts);</span><br><span class="line">		<span class="comment">// 创建Query</span></span><br><span class="line">		Query query = multiFieldQueryParser.parse(<span class="string">&quot;冰箱&quot;</span>);</span><br><span class="line">		searcher(query);</span><br><span class="line">	&#125;</span><br></pre></td></tr></table></figure>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh">
    <link itemprop="mainEntityOfPage" href="https://suyuhuan.gitee.io/yuwanzi.io/2016/06/17/2016-06-17-springmvc-02/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/yuwanzi.io/images/avatar.gif">
      <meta itemprop="name" content="玉丸子">
      <meta itemprop="description" content="这里是玉丸子的个人博客,与你一起发现更大的世界。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="玉丸子 | Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/yuwanzi.io/2016/06/17/2016-06-17-springmvc-02/" class="post-title-link" itemprop="url">Spring MVC进阶应用</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Veröffentlicht am</span>

      <time title="Erstellt: 2016-06-17 00:00:00" itemprop="dateCreated datePublished" datetime="2016-06-17T00:00:00+08:00">2016-06-17</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">Bearbeitet am</span>
        <time title="Geändert am: 2020-11-07 08:58:17" itemprop="dateModified" datetime="2020-11-07T08:58:17+08:00">2020-11-07</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">in</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">后端</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Java/Spring/" itemprop="url" rel="index"><span itemprop="name">Spring</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="Spring-MVC-进阶应用"><a href="#Spring-MVC-进阶应用" class="headerlink" title="Spring MVC 进阶应用"></a>Spring MVC 进阶应用</h2><h3 id="参数绑定"><a href="#参数绑定" class="headerlink" title="参数绑定"></a>参数绑定</h3><p> 客户端发送请求时传递的参数默认是键值对格式,<code>Spring MVC</code>通过参数绑定组件将请求的参数串进行类型转换。<br> <code>Spring MVC</code>使用Controller方法的形参接收请求传来的参数。</p>
<h4 id="1-Spring-MVC默认内置的形参类型"><a href="#1-Spring-MVC默认内置的形参类型" class="headerlink" title="1. Spring MVC默认内置的形参类型"></a>1. Spring MVC默认内置的形参类型</h4><ul>
<li>HttpServletRequest </li>
<li>HttpServletResponse </li>
<li>HttpSession </li>
<li>Model 一个接口,可以将数据填充到request域对象中。</li>
<li>ModelMap Model接口的实现。</li>
</ul>
<p>这5个对象可以直接通过形参注入并使用。</p>
<h4 id="2-简单数据类型绑定"><a href="#2-简单数据类型绑定" class="headerlink" title="2. 简单数据类型绑定"></a>2. 简单数据类型绑定</h4><p>前端页面表单中的name或者URL中的key与Controller方法中的形参名称一致,即可完成绑定。<br>如果名称不一致,可以使用<code>@RequestParam</code>注解指定名称完成绑定。<br>例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">URL: http:<span class="comment">//xxxxx?SID=1</span></span><br><span class="line"></span><br><span class="line">Controller:</span><br><span class="line"><span class="comment">// 将SID的数据封装到形参id中。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">update</span> <span class="params">(<span class="meta">@RequestParam(&quot;SID&quot;)</span> Integer id,Model model)</span> </span></span><br></pre></td></tr></table></figure>
<p><strong>RequestParam注解</strong></p>
<ul>
<li>value:参数名,即传入参数的名称。</li>
<li>required:默认为true,表示请求中要有相应的参数,否则报错:Status 400 - Required Integer parameter ‘XXXX’ is not present</li>
<li>defaultValue:默认值,没有同名参数时,则使用默认值。</li>
</ul>
<h4 id="3-JavaBean对象类型绑定"><a href="#3-JavaBean对象类型绑定" class="headerlink" title="3. JavaBean对象类型绑定"></a>3. JavaBean对象类型绑定</h4><p>前端页面表单中的name或者URL中的key与JavaBean中的属性名进行匹配。<br>如果参数名称一致,则将参数绑定到JavaBean中的属性上。<br>如果JavaBean中包装了对象类型,传入参数的名称则需要按照 对象.属性 的格式编写,并且属性要与JavaBean中包装的对象中的属性名称一致。</p>
<h4 id="4-集合类型绑定"><a href="#4-集合类型绑定" class="headerlink" title="4. 集合类型绑定"></a>4. 集合类型绑定</h4><p><strong>数组类型绑定</strong><br>使用checkbox复选框时,会将参数绑定到一个数组中。<br>例如:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">前端页面:</span><br><span class="line">&lt;input type=<span class="string">&quot;checkbox&quot;</span> name=<span class="string">&quot;cId&quot;</span> value=<span class="string">&quot;1&quot;</span>&gt;</span><br><span class="line">&lt;input type=<span class="string">&quot;checkbox&quot;</span> name=<span class="string">&quot;cId&quot;</span> value=<span class="string">&quot;2&quot;</span>&gt;</span><br><span class="line"></span><br><span class="line">Controller:</span><br><span class="line"><span class="comment">// 使用一个数组接收复选框的参数</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">delete</span> <span class="params">(Integer[] cId,Model model)</span> </span></span><br></pre></td></tr></table></figure>
<p><strong>List集合类型绑定</strong><br>Controller不能直接在形参中定义List,需要在包装类中定义List。<br>页面中的编写格式: list名[index].属性名<br>例如:</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;c:forEach items=&quot;$&#123;list&#125;&quot; var=&quot;user&quot; varStatus=&quot;status&quot;&gt;</span><br><span class="line">    <span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">name</span>=<span class="string">&quot;list[$&#123;status.index&#125;].name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;user.name&#125;&quot;</span> /&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">&lt;/c:forEach&gt;</span><br></pre></td></tr></table></figure>
<p><strong>Map集合类型绑定</strong><br>Controller不能直接在形参中定义Map,需要在包装类中定义Map。<br>页面中的编写格式:map名[‘key’]<br>例如:</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;c:forEach items=&quot;$&#123;list&#125;&quot; var=&quot;user&quot; varStatus=&quot;status&quot;&gt;</span><br><span class="line">    <span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">name</span>=<span class="string">&quot;map[&#x27;name&#x27;]&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;user.name&#125;&quot;</span> /&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">&lt;/c:forEach&gt;</span><br></pre></td></tr></table></figure>
<h3 id="Converter"><a href="#Converter" class="headerlink" title="Converter"></a>Converter</h3><p>当请求参数中含有日期类型时,需要自定义一个类型转换器转换成我们需要的日期格式。<br>创建一个类实现Converter接口就可以自定义一个类型转换器。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Converter&lt;需要转换的数据的类型,转换的类型&gt;</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DateConverter</span> <span class="keyword">implements</span> <span class="title">Converter</span>&lt;<span class="title">String</span>, <span class="title">Date</span>&gt; </span>&#123;</span><br><span class="line"></span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> Date <span class="title">convert</span><span class="params">(String source)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">try</span>&#123;</span><br><span class="line">			<span class="comment">// 转换日期格式</span></span><br><span class="line">			SimpleDateFormat format = <span class="keyword">new</span> SimpleDateFormat(<span class="string">&quot;yyyy-MM-dd HH:mm:ss&quot;</span>);</span><br><span class="line">			<span class="keyword">return</span> format.parse(source);</span><br><span class="line">		&#125;<span class="keyword">catch</span>(Exception e)&#123;</span><br><span class="line">			e.printStackTrace();</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="comment">// 出现异常,则返回null</span></span><br><span class="line">		<span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>之后需要在处理器适配器中注册Converter</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 注册注解方式的适配器与映射器 --&gt;</span><br><span class="line">&lt;mvc:annotation-driven conversion-service=<span class="string">&quot;conversionService&quot;</span> /&gt;</span><br><span class="line"></span><br><span class="line">&lt;bean id=<span class="string">&quot;conversionService&quot;</span></span><br><span class="line">	class=<span class="string">&quot;org.springframework.format.support.FormattingConversionServiceFactoryBean&quot;</span>&gt;</span><br><span class="line">	&lt;property name=<span class="string">&quot;converters&quot;</span>&gt;</span><br><span class="line">		&lt;list&gt;</span><br><span class="line">			&lt;!-- 日期类型转换器 --&gt;</span><br><span class="line">			&lt;bean class=<span class="string">&quot;com.sun.ssm.converter.DateConverter&quot;</span>&gt;&lt;/bean&gt;</span><br><span class="line">		&lt;/list&gt;</span><br><span class="line">	&lt;/property&gt;</span><br><span class="line">&lt;/bean&gt;</span><br></pre></td></tr></table></figure>
<h3 id="Validation"><a href="#Validation" class="headerlink" title="Validation"></a>Validation</h3><p>Spring MVC本身没有实现表现层校验的部分，它本身支持JSR 303校验规范，而这个规范的官方参考实现是hibernate validator。</p>
<p>所以Spring MVC想要实现校验,需要导入Hibernate-validator jar包。</p>
<p>在配置文件中配置validator校验器</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 配置校验器 --&gt;</span><br><span class="line">&lt;bean id=<span class="string">&quot;validator&quot;</span> class=<span class="string">&quot;org.springframework.validation.beanvalidation.LocalValidatorFactoryBean&quot;</span>&gt;</span><br><span class="line">	&lt;!-- 校验器提供者 --&gt;</span><br><span class="line">	&lt;property name=<span class="string">&quot;providerClass&quot;</span> value=<span class="string">&quot;org.hibernate.validator.HibernateValidator&quot;</span> /&gt;</span><br><span class="line">	&lt;!-- 指定校验使用的资源文件，在文件中配置校验错误信息，</span><br><span class="line">			如果不指定，默认使用classpath下的ValidationMessages<span class="selector-class">.properties</span> </span><br><span class="line">	--&gt;</span><br><span class="line">	&lt;property name=<span class="string">&quot;validationMessageSource&quot;</span> ref=<span class="string">&quot;messageSource&quot;</span> /&gt;</span><br><span class="line">&lt;/bean&gt;</span><br><span class="line">	</span><br><span class="line">&lt;!-- 校验错误信息的资源文件 --&gt;</span><br><span class="line">&lt;bean id=<span class="string">&quot;messageSource&quot;</span> class=<span class="string">&quot;org.springframework.context.support.ReloadableResourceBundleMessageSource&quot;</span>&gt;</span><br><span class="line">	&lt;!-- 指定文件路径 --&gt;</span><br><span class="line">	&lt;property name=<span class="string">&quot;basenames&quot;</span>&gt;</span><br><span class="line">		&lt;list&gt;</span><br><span class="line">			&lt;value&gt;classpath:validationMessages&lt;/value&gt;</span><br><span class="line">		&lt;/list&gt;</span><br><span class="line">	&lt;/property&gt;</span><br><span class="line">	&lt;!-- 指定文件的编码 --&gt;</span><br><span class="line">	&lt;property name=<span class="string">&quot;fileEncodings&quot;</span> value=<span class="string">&quot;utf8&quot;</span>/&gt;</span><br><span class="line">	&lt;!-- 资源文件内容缓存的时间，单位秒 --&gt;</span><br><span class="line">	&lt;property name=<span class="string">&quot;cacheSeconds&quot;</span> value=<span class="string">&quot;120&quot;</span> /&gt;</span><br><span class="line">&lt;/bean&gt;</span><br></pre></td></tr></table></figure>
<p>在处理器适配器中注册Validator</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 注册注解方式的适配器与映射器 --&gt;</span><br><span class="line">&lt;mvc:annotation-driven conversion-service=<span class="string">&quot;conversionService&quot;</span> validator=<span class="string">&quot;validator&quot;</span> /&gt;</span><br></pre></td></tr></table></figure>
<p>在JavaBean中可以使用注解制定校验规则。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ValidationMessages.properties:</span><br><span class="line">    user.username.size.error=用户名长度格式为<span class="number">1</span>-<span class="number">10</span>之间</span><br><span class="line"></span><br><span class="line">JavaBean:</span><br><span class="line"> <span class="meta">@Size(min=1,max=10,message=&quot;&#123;user.username.size.error&#125;&quot;)</span></span><br><span class="line"> <span class="keyword">private</span> String username;</span><br></pre></td></tr></table></figure>
<p>Controller中在需要检验的形参前使用<code>@Validated</code>注解,并在形参中注入一个BindingResult对象接收校验错误信息。<br><code>@Validated</code>注解和BindingResult顺序是固定的。(<code>@Validated</code>在前)</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;/updateUser&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">updateUser</span><span class="params">(<span class="meta">@Validated</span> User user,BindingResult bindingResult,Model model)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 判断是否有校验错误信息,如果有则代表校验未通过</span></span><br><span class="line">	<span class="keyword">if</span>(bindingResult.hasErrors())&#123;</span><br><span class="line">	    <span class="comment">// 获得校验错误信息集合</span></span><br><span class="line">		List&lt;ObjectError&gt; allErrors = bindingResult.getAllErrors();</span><br><span class="line">		<span class="comment">// 将校验错误信息集合存入request域中</span></span><br><span class="line">		model.addAttribute(<span class="string">&quot;errors&quot;</span>, allErrors);</span><br><span class="line">			</span><br><span class="line">		<span class="comment">//检验未通过,重新跳转到修改页面</span></span><br><span class="line">		<span class="keyword">return</span> <span class="string">&quot;updateUser&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>分组校验</strong></p>
<p>因为校验规则是在JavaBean中定义的,所以当同一个JavaBean需要被多个Controller使用时,可能根据需求需要不同的校验。</p>
<p>在这种情况下,可以使用一个标识作用的接口进行分组。</p>
<p>定义一个空接口作为分组的标识:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">ValidationGroup</span> </span>&#123;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在JavaBean中使用分组:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Size(min=1,max=10,message=&quot;&#123;user.username.size.error&#125;&quot;,groups=&#123;ValidationGroup.class&#125;)</span></span><br><span class="line"><span class="keyword">private</span> String username;</span><br></pre></td></tr></table></figure>
<p>在Controller中使用分组校验:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;/updateUser&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">updateUser</span><span class="params">(<span class="meta">@Validated(value=&#123;ValidationGroup.class&#125;)</span> User user,</span></span></span><br><span class="line"><span class="function"><span class="params">                            BindingResult bindingResult,Model model)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 判断是否有校验错误信息,如果有则代表校验未通过</span></span><br><span class="line">	<span class="keyword">if</span>(bindingResult.hasErrors())&#123;</span><br><span class="line">	    <span class="comment">// 获得校验错误信息集合</span></span><br><span class="line">		List&lt;ObjectError&gt; allErrors = bindingResult.getAllErrors();</span><br><span class="line">		<span class="comment">// 将校验错误信息集合存入request域中</span></span><br><span class="line">		model.addAttribute(<span class="string">&quot;errors&quot;</span>, allErrors);</span><br><span class="line">			</span><br><span class="line">		<span class="comment">//检验未通过,重新跳转到修改页面</span></span><br><span class="line">		<span class="keyword">return</span> <span class="string">&quot;updateUser&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>主要的验证注解如下:</p>
<table>
<thead>
<tr>
<th>注解</th>
<th>适用的数据类型</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>@AssertFalse</td>
<td>Boolean, boolean</td>
<td>验证注解的元素值是false</td>
</tr>
<tr>
<td>@AssertTrue</td>
<td>Boolean, boolean</td>
<td>验证注解的元素值是true</td>
</tr>
<tr>
<td>@DecimalMax（value=x）</td>
<td>BigDecimal, BigInteger, String, byte,short, int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number andCharSequence.</td>
<td>验证注解的元素值小于等于@ DecimalMax指定的value值</td>
</tr>
<tr>
<td>@DecimalMin（value=x）</td>
<td>BigDecimal, BigInteger, String, byte,short, int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number andCharSequence.</td>
<td>验证注解的元素值小于等于@ DecimalMin指定的value值</td>
</tr>
<tr>
<td>@Digits(integer=整数位数, fraction=小数位数)</td>
<td>BigDecimal, BigInteger, String, byte,short, int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number andCharSequence.</td>
<td>验证注解的元素值的整数位数和小数位数上限</td>
</tr>
<tr>
<td>@Future</td>
<td>java.util.Date, java.util.Calendar; Additionally supported by HV, if theJoda Time date/time API is on the class path: any implementations ofReadablePartial andReadableInstant.</td>
<td>验证注解的元素值（日期类型）比当前时间晚</td>
</tr>
<tr>
<td>@Max（value=x）</td>
<td>BigDecimal, BigInteger, byte, short,int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type ofCharSequence (the numeric value represented by the character sequence is evaluated), any sub-type of Number.</td>
<td>验证注解的元素值小于等于@Max指定的value值</td>
</tr>
<tr>
<td>@Min（value=x）</td>
<td>BigDecimal, BigInteger, byte, short,int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of CharSequence (the numeric value represented by the char sequence is evaluated), any sub-type of Number.</td>
<td>验证注解的元素值大于等于@Min指定的value值</td>
</tr>
<tr>
<td>@NotNull</td>
<td>Any type</td>
<td>验证注解的元素值不是null</td>
</tr>
<tr>
<td>@Null</td>
<td>Any type</td>
<td>验证注解的元素值是null</td>
</tr>
<tr>
<td>@Past</td>
<td>java.util.Date, java.util.Calendar; Additionally supported by HV, if theJoda Time date/time API is on the class path: any implementations ofReadablePartial andReadableInstant.</td>
<td>验证注解的元素值（日期类型）比当前时间早</td>
</tr>
<tr>
<td>@Pattern(regex=正则表达式, flag=)</td>
<td>String. Additionally supported by HV: any sub-type of CharSequence.</td>
<td>验证注解的元素值与指定的正则表达式匹配</td>
</tr>
<tr>
<td>@Size(min=最小值, max=最大值)</td>
<td>String, Collection, Map and arrays. Additionally supported by HV: any sub-type of CharSequence.</td>
<td>验证注解的元素值的在min和max（包含）指定区间之内，如字符长度、集合大小</td>
</tr>
<tr>
<td>@Valid</td>
<td>Any non-primitive type（引用类型）</td>
<td>验证关联的对象，如账户对象里有一个订单对象，指定验证订单对象</td>
</tr>
<tr>
<td>@NotEmpty</td>
<td>CharSequence,Collection, Map and Arrays</td>
<td>验证注解的元素值不为null且不为空（字符串长度不为0、集合大小不为0）</td>
</tr>
<tr>
<td>@Range(min=最小值, max=最大值)</td>
<td>CharSequence, Collection, Map and Arrays,BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types</td>
<td>验证注解的元素值在最小值和最大值之间</td>
</tr>
<tr>
<td>@NotBlank</td>
<td>CharSequence</td>
<td>验证注解的元素值不为空（不为null、去除首位空格后长度为0），不同于@NotEmpty，@NotBlank只应用于字符串且在比较时会去除字符串的空格</td>
</tr>
<tr>
<td>@Length(min=下限, max=上限)</td>
<td>CharSequence</td>
<td>验证注解的元素值长度在min和max区间内</td>
</tr>
<tr>
<td>@Email</td>
<td>CharSequence</td>
<td>验证注解的元素值是Email，也可以通过正则表达式和flag指定自定义的email格式</td>
</tr>
</tbody></table>
<h3 id="数据回显"><a href="#数据回显" class="headerlink" title="数据回显"></a>数据回显</h3><p>Spring MVC默认支持数据回显。</p>
<p>Spring MVC会在Controller返回之前,自动将形参中的JavaBean放入Request域中,默认名称为类名首字母小写。<br>只要前端页面动态获取数据的key与JavaBean名称一致,即可完成数据回显。<br>如果名称不一致,也可以用<code>@ModelAttribute</code>注解指定形参放入Request域中的key名。</p>
<h3 id="文件上传"><a href="#文件上传" class="headerlink" title="文件上传"></a>文件上传</h3><p>Spring MVC使用Multipart解析器完成文件上传,而Multipart解析器需要依赖以下2个jar包:</p>
<ul>
<li>commons-fileupload</li>
<li>commons-io</li>
</ul>
<p><strong>配置Multipart解析器</strong></p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;bean id=<span class="string">&quot;multipartResolver&quot;</span> class=<span class="string">&quot;org.springframework.web.multipart.commons.CommonsMultipartResolver&quot;</span>&gt;</span><br><span class="line">    &lt;!-- 限制上传文件的最大长度 --&gt;</span><br><span class="line">    &lt;property name=<span class="string">&quot;maxUploadSize&quot;</span> value=<span class="string">&quot;10*1024*1024&quot;</span>/&gt;</span><br><span class="line">&lt;/bean&gt;</span><br></pre></td></tr></table></figure>
<p>需要在Controller形参中注入一个MultipartFile对象接收文件,该对象名字要与传入的文件名相同。<br><strong>文件上传示例</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 判断是否上传了文件</span></span><br><span class="line"><span class="keyword">if</span>(file!= <span class="keyword">null</span>)&#123;</span><br><span class="line">		<span class="comment">//原始文件名称</span></span><br><span class="line">		String fileName = file.getOriginalFilename();</span><br><span class="line">		<span class="comment">//判断文件名是否为空</span></span><br><span class="line">		<span class="keyword">if</span>(fileName != <span class="keyword">null</span> &amp;&amp; !<span class="string">&quot;&quot;</span>.equals(fileName))</span><br><span class="line">		&#123;</span><br><span class="line">			<span class="comment">// 文件存放的路径</span></span><br><span class="line">			String path = <span class="string">&quot;D:\\temps\\&quot;</span>;</span><br><span class="line">		    <span class="comment">// 判断文件存放路径是否存在</span></span><br><span class="line">		    File dirFile = <span class="keyword">new</span> File(path);</span><br><span class="line">		    <span class="comment">// 文件夹不存在,自动创建一个文件夹</span></span><br><span class="line">		    <span class="keyword">if</span>(!dirFile.exists()) &#123;</span><br><span class="line">		        dirFile.mkdirs();</span><br><span class="line">		    &#125;</span><br><span class="line">		    <span class="comment">// 使用UUID拼接一个唯一文件名</span></span><br><span class="line">			String newFileName = UUID.randomUUID()+fileName.substring(fileName.lastIndexOf(<span class="string">&quot;.&quot;</span>));</span><br><span class="line">			<span class="comment">//新的文件</span></span><br><span class="line">			File newFile = <span class="keyword">new</span> File(path+newFileName);</span><br><span class="line">			<span class="comment">//把上传的文件保存成一个新的文件</span></span><br><span class="line">			file.transferTo(newFile);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br></pre></td></tr></table></figure>
<h3 id="Interceptor"><a href="#Interceptor" class="headerlink" title="Interceptor"></a>Interceptor</h3><p>Spring MVC的拦截器是针对处理器进行拦截的,当HandlerMapping查找处理器时,会被拦截器拦截。</p>
<p>可以通过实现HandlerIntercepter接口,自定义一个拦截器。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyHandlerInterceptor</span> <span class="keyword">implements</span> <span class="title">HandlerInterceptor</span></span>&#123;</span><br><span class="line"></span><br><span class="line">	<span class="comment">// Handler执行前调用,返回值为true则放行,false则不放行。</span></span><br><span class="line">	<span class="comment">// 应用场景:登录验证,权限授权</span></span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">preHandle</span><span class="params">(HttpServletRequest request,HttpServletResponse response, </span></span></span><br><span class="line"><span class="function"><span class="params">	                    Object handler)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">		</span><br><span class="line">		</span><br><span class="line">		<span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="comment">// Handler开始执行,并且在返回ModelAndView之前调用</span></span><br><span class="line">	<span class="comment">// 应用场景:操作ModelAndView对象</span></span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">postHandle</span><span class="params">(HttpServletRequest request,HttpServletResponse response, Object handler,</span></span></span><br><span class="line"><span class="function"><span class="params">			ModelAndView modelAndView)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">		</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="comment">// Handler执行完后调用</span></span><br><span class="line">	<span class="comment">// 应用场景:异常处理、日志</span></span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterCompletion</span><span class="params">(HttpServletRequest request,</span></span></span><br><span class="line"><span class="function"><span class="params">			HttpServletResponse response, Object handler, Exception ex)</span></span></span><br><span class="line"><span class="function">			<span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">		</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>配置拦截器</strong></p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 配置全局拦截器 --&gt;</span><br><span class="line">&lt;mvc:interceptors&gt;</span><br><span class="line">	&lt;mvc:interceptor&gt;</span><br><span class="line">		&lt;!-- <span class="comment">/**表示所有URL和子URL路径 --&gt;</span></span><br><span class="line"><span class="comment">		&lt;mvc:mapping path=&quot;/**&quot; /&gt;</span></span><br><span class="line"><span class="comment">		&lt;bean class=&quot;com.sun.interceptor.MyHandlerInterceptor&quot; /&gt;</span></span><br><span class="line"><span class="comment">	&lt;/mvc:interceptor&gt;</span></span><br><span class="line"><span class="comment">&lt;/mvc:interceptors&gt;</span></span><br></pre></td></tr></table></figure>
<p><strong>拦截器的执行顺序</strong></p>
<ul>
<li>preHandle()为正向顺序执行,postHandle()和afterCompletion()为逆向顺序执行。</li>
<li>如果第一个拦截器返回值为false,那它之后所有的拦截器都不会执行。</li>
<li>如果一个拦截器返回值为false,那么它的postHandle()和afterCompletion()都不会执行。</li>
<li>只要有一个拦截器的返回值为false,则所有拦截器的postHandle()都不会执行。</li>
</ul>
<h3 id="RESTful"><a href="#RESTful" class="headerlink" title="RESTful"></a>RESTful</h3><blockquote>
<p>一种软件架构风格，设计风格而不是标准，只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁，更有层次，更易于实现缓存等机制。</p>
</blockquote>
<p>实现REST风格需要在DispatcherServlet中将url映射模式改为 / </p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;servlet-mapping&gt;</span><br><span class="line">    &lt;servlet-name&gt;springmvc&lt;/servlet-name&gt;</span><br><span class="line">    &lt;url-pattern&gt;/&lt;/url-pattern&gt;</span><br><span class="line">&lt;/servlet-mapping&gt;</span><br></pre></td></tr></table></figure>
<p>但是当映射模式为/时会把静态资源一起拦截,需要配置才能访问静态资源。</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;mvc:resources location=<span class="string">&quot;/js/&quot;</span> mapping=<span class="string">&quot;/js/**&quot;</span>/&gt;</span><br><span class="line">&lt;mvc:resources location=<span class="string">&quot;/css/&quot;</span> mapping=<span class="string">&quot;/css/**&quot;</span>/&gt;</span><br><span class="line">&lt;mvc:resources location=<span class="string">&quot;/jquery/&quot;</span> mapping=<span class="string">&quot;/jquery/**&quot;</span>/&gt;</span><br></pre></td></tr></table></figure>
<p>Springmvc会把mapping映射到ResourceHttpRequestHandler，这样静态资源在经过DispatcherServlet转发时就可以找到对应的Handler了。</p>
<p><strong>在Controller中实现RESTful</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;/update/&#123;id&#125;&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">update</span><span class="params">(<span class="meta">@PathVariable</span> Integer id,Model model)</span></span></span><br></pre></td></tr></table></figure>
<ul>
<li><code>@PathVariable</code>:将URL中的模板变量映射到形参上,如果形参与模板变量名称不一致,可以使用value=” “设置为模板变量的名称完成映射。</li>
<li>{id}:模板变量。例如URL为 xxxx/update/1,模板变量update/{id}就可以将1封装到{id}中。</li>
</ul>
<h3 id="JSON"><a href="#JSON" class="headerlink" title="JSON"></a>JSON</h3><p>Spring MVC默认使用MappingJacksonHttpMessageConverter对json数据进行转换，所以需要导入Jackson的jar包。</p>
<p>Spring MVC可以使用2个注解完成JSON数据的交互操作。</p>
<ul>
<li><code>@RequestBody</code>:如果请求参数传入的是json数据,使用<code>RequestBody</code>可以将json转换为java对象。</li>
<li><code>@ResponseBody</code>:将返回值的java对象转换为json输出。</li>
</ul>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh">
    <link itemprop="mainEntityOfPage" href="https://suyuhuan.gitee.io/yuwanzi.io/2016/06/15/2016-06-15-springmvc-process/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/yuwanzi.io/images/avatar.gif">
      <meta itemprop="name" content="玉丸子">
      <meta itemprop="description" content="这里是玉丸子的个人博客,与你一起发现更大的世界。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="玉丸子 | Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/yuwanzi.io/2016/06/15/2016-06-15-springmvc-process/" class="post-title-link" itemprop="url">Spring MVC原理及流程</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Veröffentlicht am</span>

      <time title="Erstellt: 2016-06-15 00:00:00" itemprop="dateCreated datePublished" datetime="2016-06-15T00:00:00+08:00">2016-06-15</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">Bearbeitet am</span>
        <time title="Geändert am: 2020-11-07 08:58:17" itemprop="dateModified" datetime="2020-11-07T08:58:17+08:00">2020-11-07</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">in</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">后端</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Java/Spring/" itemprop="url" rel="index"><span itemprop="name">Spring</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h3 id="Spring-MVC介绍"><a href="#Spring-MVC介绍" class="headerlink" title="Spring MVC介绍"></a>Spring MVC介绍</h3><ol>
<li>Spring MVC属于SpringFrameWork的后续产品，已经融合在Spring Web Flow里面。</li>
<li>通过策略接口，Spring MVC是高度可配置的，而且包含多种视图技术，例如 JavaServer Pages（JSP）、Velocity、Tiles、iText和POI。</li>
<li>使用 Spring 可插入的MVC架构，从而在使用Spring进行WEB开发时，可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架，如Struts1，Struts2等。</li>
<li>Spring MVC是一个完全基于MVC模式(Model、View、Controller)的框架。</li>
</ol>
<h3 id="Spring-MVC工作原理"><a href="#Spring-MVC工作原理" class="headerlink" title="Spring MVC工作原理"></a>Spring MVC工作原理</h3><p><img src="http://ww1.sinaimg.cn/mw690/63503acbjw1f4v325kscyj20ui0qi776.jpg"></p>
<p>Spring MVC工作流程:</p>
<ol>
<li>用户发起请求。</li>
<li>DispatcherServlet接收到请求,并去调用HandlerMapping查找处理器。</li>
<li>HandlerMapping根据请求的URL查找对应的处理器,并返回给前端控制器DispatcherServlet。</li>
<li>DispatcherServlet调用HandlerAdapter执行处理器。</li>
<li>HandlerAdapter先判断处理器的类型进行适配,然后执行处理器。</li>
<li>处理器进行数据和业务请求的处理,将ModelAndView对象返回给HandlerAdapter。</li>
<li>HandlerAdapter将ModelAndView对象返回到前端控制器DispatcherServlet。</li>
<li>DispatcherServlet调用ViewResolver解析逻辑视图ModelAndView。</li>
<li>ViewResolver通过逻辑视图的名称查找对应的视图对象,并返回给前端控制器。</li>
<li>DispatcherServlet调用View渲染视图到前端。</li>
<li>响应处理的结果。</li>
</ol>
<p>Spring MVC主要由以下几个部分组成:</p>
<ul>
<li>前端控制器(DispatcherServlet):接收请求并响应到前端,并且负责各组件职责的分派。</li>
<li>处理器(Handler):处理数据与业务请求,Handler需要符合适配器的规则。</li>
<li>处理器映射器(HandlerMapping):根据每个请求的URL查找对应的处理器Handler。</li>
<li>处理器适配器(HandlerAdapter):根据类型适配每个处理器Handler并执行。</li>
<li>视图解析器(ViewResolver):根据逻辑视图的名称将逻辑视图解析为视图对象。</li>
<li>视图(View):在Spring MVC中,View是一个接口,通过不同的实现类支持不同的类型。(jsp、freemarker等)</li>
</ul>
<p>注：</p>
<ul>
<li>DispatcherServlet在创建时会默认从DispatcherServlet.properties中加载springmvc的各个组件配置。</li>
<li>如果在servletname-servlet.xml(Spring MVC配置文件)中配置了各个组件的配置则会优先使用servletname-servlet.xml中的配置。</li>
</ul>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh">
    <link itemprop="mainEntityOfPage" href="https://suyuhuan.gitee.io/yuwanzi.io/2016/06/12/2016-06-12-mybatis-study%20notes02/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/yuwanzi.io/images/avatar.gif">
      <meta itemprop="name" content="玉丸子">
      <meta itemprop="description" content="这里是玉丸子的个人博客,与你一起发现更大的世界。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="玉丸子 | Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/yuwanzi.io/2016/06/12/2016-06-12-mybatis-study%20notes02/" class="post-title-link" itemprop="url">MyBatis学习笔记-02</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Veröffentlicht am</span>

      <time title="Erstellt: 2016-06-12 00:00:00" itemprop="dateCreated datePublished" datetime="2016-06-12T00:00:00+08:00">2016-06-12</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">Bearbeitet am</span>
        <time title="Geändert am: 2020-11-07 08:58:17" itemprop="dateModified" datetime="2020-11-07T08:58:17+08:00">2020-11-07</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">in</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">后端</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Java/MyBatis/" itemprop="url" rel="index"><span itemprop="name">MyBatis</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <p><img src="http://ww3.sinaimg.cn/mw690/63503acbjw1f4pf96s0tcj209302caa2.jpg" alt="MyBatis"></p>
<h3 id="关联映射"><a href="#关联映射" class="headerlink" title="关联映射"></a>关联映射</h3><h4 id="1-业务关系分析"><a href="#1-业务关系分析" class="headerlink" title="1. 业务关系分析"></a>1. 业务关系分析</h4><p>在进行多表关联查询之前,需要对表结构的关联关系与业务关系进行分析与理解。<br>下图以用户,订单,明细,商品表为例分析:<br><img src="http://ww2.sinaimg.cn/mw690/63503acbjw1f4tl89vexqj20fd0ba74p.jpg" alt="数据模型分析"></p>
<ul>
<li>用户表与订单表<ul>
<li>一个用户可以创建多个订单 (一对多)</li>
<li>一个订单只能由一个用户创建(一对一)</li>
</ul>
</li>
<li>订单表与明细表<ul>
<li>一个订单可以含有多个订单明细(一对多)</li>
<li>一个订单明细只能对应一个订单(一对一)</li>
</ul>
</li>
<li>明细表与商品表<ul>
<li>一个订单明细只能对应一个商品(一对一)</li>
<li>一个商品可以被包含在多个订单明细中(一对多)</li>
</ul>
</li>
<li>订单表与商品表 (间接关系)<ul>
<li>一个订单可以拥有多个订单明细,而一个订单明细对应一个商品,即一个订单可以拥有多个商品。<ul>
<li>order -&gt; orderdetail -&gt; items 一对多</li>
</ul>
</li>
<li>一个商品可以被包含在多个订单明细中,而一个订单明细对应一个订单,即一个商品可以被包含在多个订单中。<ul>
<li>item -&gt; orderdetail -&gt; order 一对多</li>
</ul>
</li>
<li>订单与商品是多对多关系。</li>
</ul>
</li>
<li>用户表与商品表 (间接关系)<ul>
<li>一个用户可以创建多个订单,一个订单可以对应多个订单明细,一个订单明细对应一个商品,即一个用户可以购买多个商品。<ul>
<li>user -&gt; order -&gt; orderdetail -&gt; item 一对多</li>
</ul>
</li>
<li>一个商品可以被包含在多个订单明细中,一个订单明细对应一个订单,一个订单对应一个用户,即一个商品可以对应多个用户。<ul>
<li>item -&gt; orderdetail -&gt; order -&gt; user 一对多</li>
</ul>
</li>
<li>用户与商品是多对多关系。</li>
</ul>
</li>
</ul>
<h4 id="2-一对一关联查询"><a href="#2-一对一关联查询" class="headerlink" title="2. 一对一关联查询"></a>2. 一对一关联查询</h4><blockquote>
<p>在多表查询时,单表的JavaBean不能满足结果集的映射,所以可以使用继承的方法来扩展JavaBean。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.sun.test.entity;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Orders的扩展类</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">OrdersExtends</span> <span class="keyword">extends</span> <span class="title">Orders</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">private</span> User user;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> User <span class="title">getUser</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">return</span> user;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setUser</span><span class="params">(User user)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.user = user;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上面的做法与在Orders类中添加一个User类型的属性作用相同。</p>
<blockquote>
<p>映射文件配置</p>
</blockquote>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">&lt;mapper namespace=<span class="string">&quot;com.sun.test.mapper.OrdersMapper&quot;</span>&gt;</span><br><span class="line"></span><br><span class="line">	&lt;!-- selectOrdersAndUserRetMap --&gt;</span><br><span class="line">	&lt;!-- resultMap可以使用extends字段继承一个type一致的resultMap  --&gt;</span><br><span class="line">	&lt;resultMap type=<span class="string">&quot;ordersExtends&quot;</span> id=<span class="string">&quot;selectOrdersAndUserRetMap&quot;</span>&gt;</span><br><span class="line">		&lt;!-- 主键 --&gt;</span><br><span class="line">		&lt;id column=<span class="string">&quot;id&quot;</span> property=<span class="string">&quot;id&quot;</span> /&gt;</span><br><span class="line">		&lt;!-- 其他字段 --&gt;</span><br><span class="line">		&lt;result column=<span class="string">&quot;user_id&quot;</span> property=<span class="string">&quot;userId&quot;</span>/&gt;</span><br><span class="line">		&lt;result column=<span class="string">&quot;number&quot;</span> property=<span class="string">&quot;number&quot;</span>/&gt;</span><br><span class="line">		&lt;result column=<span class="string">&quot;createtime&quot;</span> property=<span class="string">&quot;createtime&quot;</span>/&gt;</span><br><span class="line">		&lt;result column=<span class="string">&quot;note&quot;</span> property=<span class="string">&quot;note&quot;</span>/&gt;  </span><br><span class="line">		&lt;!-- association:一对一映射</span><br><span class="line">			 	property:关联对象在JavaBean中封装的属性名</span><br><span class="line">			 	javaType:关联对象的Java类型</span><br><span class="line">		 --&gt;</span><br><span class="line">		&lt;association property=<span class="string">&quot;user&quot;</span> javaType=<span class="string">&quot;com.sun.test.entity.User&quot;</span>&gt;</span><br><span class="line">			&lt;id column=<span class="string">&quot;user_id&quot;</span> property=<span class="string">&quot;id&quot;</span>/&gt;</span><br><span class="line">			&lt;result column=<span class="string">&quot;username&quot;</span> property=<span class="string">&quot;username&quot;</span>/&gt;</span><br><span class="line">			&lt;result column=<span class="string">&quot;address&quot;</span> property=<span class="string">&quot;address&quot;</span>/&gt;			</span><br><span class="line">		&lt;/association&gt; </span><br><span class="line">	&lt;/resultMap&gt;</span><br><span class="line">	</span><br><span class="line">	&lt;!-- 查询订单与用户信息 --&gt;</span><br><span class="line">	&lt;select id=<span class="string">&quot;selectOrdersAndUser&quot;</span> resultMap=<span class="string">&quot;selectOrdersAndUserRetMap&quot;</span>&gt;</span><br><span class="line">		SELECT</span><br><span class="line">			orders<span class="selector-class">.id</span>,</span><br><span class="line">			orders<span class="selector-class">.user_id</span>,</span><br><span class="line">			orders<span class="selector-class">.number</span>,</span><br><span class="line">			orders<span class="selector-class">.createtime</span>,</span><br><span class="line">			orders<span class="selector-class">.note</span>,</span><br><span class="line">			`user`<span class="selector-class">.username</span>,</span><br><span class="line">			`user`.address</span><br><span class="line">		FROM</span><br><span class="line">			orders,</span><br><span class="line">			`user`</span><br><span class="line">		WHERE orders<span class="selector-class">.user_id</span> = `user`.id</span><br><span class="line">	&lt;/select&gt;</span><br><span class="line">	</span><br><span class="line">&lt;/mapper&gt;</span><br></pre></td></tr></table></figure>
<h4 id="3-一对多关联查询"><a href="#3-一对多关联查询" class="headerlink" title="3. 一对多关联查询"></a>3. 一对多关联查询</h4><blockquote>
<p>一对多查询与一对一查询类似,我们要查询商品以及订单明细则需要在商品类中扩展一个List集合。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Items</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Float price;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String pic;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Date createtime;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String detail;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 一对多  一个商品对应多个订单明细</span></span><br><span class="line">    <span class="keyword">private</span> List&lt;Orderdetail&gt; orderdetails;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>映射文件配置</p>
</blockquote>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">&lt;mapper namespace=<span class="string">&quot;com.sun.test.mapper.ItemsMapper&quot;</span>&gt;</span><br><span class="line"></span><br><span class="line">	&lt;!-- (一对多)查询商品以及对应的订单明细 --&gt;</span><br><span class="line">	&lt;select id=<span class="string">&quot;selectItemsAndOrderdetail&quot;</span> resultMap=<span class="string">&quot;selectItemsAndOrderdetailRetMap&quot;</span>&gt;</span><br><span class="line">		SELECT</span><br><span class="line">			items<span class="selector-class">.id</span>,</span><br><span class="line">			items.`name`,</span><br><span class="line">			items<span class="selector-class">.price</span>,</span><br><span class="line">			orderdetail<span class="selector-class">.id</span> orderdetail_id,</span><br><span class="line">			orderdetail.items_num</span><br><span class="line">		FROM</span><br><span class="line">			items,</span><br><span class="line">			orderdetail</span><br><span class="line">		WHERE</span><br><span class="line">			items.id = orderdetail.items_id;</span><br><span class="line">	&lt;/select&gt;</span><br><span class="line"></span><br><span class="line">	&lt;!-- selectItemsAndOrderdetailRetMap --&gt;</span><br><span class="line">	&lt;resultMap type=<span class="string">&quot;items&quot;</span> id=<span class="string">&quot;selectItemsAndOrderdetailRetMap&quot;</span>&gt;</span><br><span class="line">		&lt;id column=<span class="string">&quot;id&quot;</span> property=<span class="string">&quot;id&quot;</span>/&gt;</span><br><span class="line">		&lt;result column=<span class="string">&quot;name&quot;</span> property=<span class="string">&quot;name&quot;</span>/&gt;</span><br><span class="line">		&lt;result column=<span class="string">&quot;price&quot;</span> property=<span class="string">&quot;price&quot;</span>/&gt;</span><br><span class="line">		&lt;!-- 一对多关联</span><br><span class="line">			 collection:一对多映射</span><br><span class="line">			 	ofType:这个集合参数的类型</span><br><span class="line">		 --&gt;</span><br><span class="line">		 &lt;collection property=<span class="string">&quot;orderdetails&quot;</span> ofType=<span class="string">&quot;orderdetail&quot;</span>&gt;</span><br><span class="line">		 	&lt;id column=<span class="string">&quot;orderdetail_id&quot;</span> property=<span class="string">&quot;id&quot;</span>/&gt;</span><br><span class="line">		 	&lt;result column=<span class="string">&quot;items_num&quot;</span> property=<span class="string">&quot;itemsNum&quot;</span>/&gt;</span><br><span class="line">		 &lt;/collection&gt;</span><br><span class="line">	&lt;/resultMap&gt;</span><br><span class="line"></span><br><span class="line">&lt;/mapper&gt;</span><br></pre></td></tr></table></figure>
<h4 id="4-多对多关联查询"><a href="#4-多对多关联查询" class="headerlink" title="4. 多对多关联查询"></a>4. 多对多关联查询</h4><blockquote>
<p>查询商品以及对应的用户信息。</p>
<ol>
<li>在商品类中添加一个订单明细集合(一个商品对应多个订单明细)</li>
<li>在订单明细类中添加一个订单属性(一个订单明细对应一个订单)</li>
<li>在订单类中添加一个用户属性(一个订单对应一个用户)</li>
</ol>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 一对多  一个商品对应多个订单明细</span></span><br><span class="line"><span class="keyword">private</span> List&lt;Orderdetail&gt; orderdetails;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 一对一 一个订单明细对应一个订单</span></span><br><span class="line"><span class="keyword">private</span> Orders orders;</span><br><span class="line"></span><br><span class="line"><span class="comment">//一对一 一个订单对应一个用户</span></span><br><span class="line"><span class="keyword">private</span> User user;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>映射文件配置</p>
</blockquote>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 查询商品以及对应的用户 --&gt;</span><br><span class="line">&lt;select id=<span class="string">&quot;selectItemsAndUser&quot;</span> resultMap=<span class="string">&quot;selectItemsAndUserRetMap&quot;</span>&gt;</span><br><span class="line">	SELECT</span><br><span class="line">		items<span class="selector-class">.id</span>,</span><br><span class="line">		items.`name`,</span><br><span class="line">		items<span class="selector-class">.price</span>,</span><br><span class="line">		`user`<span class="selector-class">.id</span> user_id,</span><br><span class="line">		`user`<span class="selector-class">.username</span>,</span><br><span class="line">		`user`<span class="selector-class">.address</span>,</span><br><span class="line">		orderdetail<span class="selector-class">.id</span> orderdetail_id,</span><br><span class="line">		orders<span class="selector-class">.id</span> orders_id</span><br><span class="line">	FROM</span><br><span class="line">		items,</span><br><span class="line">		orderdetail,</span><br><span class="line">		orders,</span><br><span class="line">		`user`</span><br><span class="line">	WHERE</span><br><span class="line">		items<span class="selector-class">.id</span> = orderdetail.items_id</span><br><span class="line">	AND orderdetail<span class="selector-class">.orders_id</span> = orders.id</span><br><span class="line">	AND orders<span class="selector-class">.user_id</span> = `user`.id</span><br><span class="line">&lt;/select&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- selectItemsAndUserRetMap --&gt;</span><br><span class="line">&lt;resultMap type=<span class="string">&quot;items&quot;</span> id=<span class="string">&quot;selectItemsAndUserRetMap&quot;</span>&gt;</span><br><span class="line">	&lt;id column=<span class="string">&quot;id&quot;</span> property=<span class="string">&quot;id&quot;</span> /&gt;</span><br><span class="line">	&lt;result column=<span class="string">&quot;name&quot;</span> property=<span class="string">&quot;name&quot;</span>/&gt;</span><br><span class="line">	&lt;result column=<span class="string">&quot;price&quot;</span> property=<span class="string">&quot;price&quot;</span>/&gt;</span><br><span class="line">	&lt;!-- 一个商品对应多个订单明细  --&gt;</span><br><span class="line">	&lt;collection property=<span class="string">&quot;orderdetails&quot;</span> ofType=<span class="string">&quot;orderdetail&quot;</span>&gt;</span><br><span class="line">		&lt;id column=<span class="string">&quot;orderdetail_id&quot;</span> property=<span class="string">&quot;id&quot;</span>/&gt;</span><br><span class="line">		&lt;!-- 一个订单明细对应一个订单 --&gt;</span><br><span class="line">		&lt;association property=<span class="string">&quot;orders&quot;</span> javaType=<span class="string">&quot;orders&quot;</span>&gt;</span><br><span class="line">			&lt;id column=<span class="string">&quot;orders_id&quot;</span> property=<span class="string">&quot;id&quot;</span>/&gt;</span><br><span class="line">			&lt;!-- 一个订单对应一个用户 --&gt;</span><br><span class="line">			&lt;association property=<span class="string">&quot;user&quot;</span> javaType=<span class="string">&quot;user&quot;</span>&gt;</span><br><span class="line">				&lt;id column=<span class="string">&quot;user_id&quot;</span> property=<span class="string">&quot;id&quot;</span>/&gt;</span><br><span class="line">				&lt;result column=<span class="string">&quot;username&quot;</span> property=<span class="string">&quot;username&quot;</span>/&gt;</span><br><span class="line">				&lt;result column=<span class="string">&quot;address&quot;</span> property=<span class="string">&quot;address&quot;</span>/&gt;</span><br><span class="line">			&lt;/association&gt;</span><br><span class="line">		&lt;/association&gt;</span><br><span class="line">	&lt;/collection&gt;</span><br><span class="line">&lt;/resultMap&gt;</span><br></pre></td></tr></table></figure>
<h3 id="延迟加载"><a href="#延迟加载" class="headerlink" title="延迟加载"></a>延迟加载</h3><p>resultMap中的association和collection具有延迟加载的功能。</p>
<blockquote>
<p>延迟加载: 先加载主信息,在需要的时候加载关联信息,延迟加载即叫按需加载,也叫懒加载。</p>
</blockquote>
<h4 id="1-设置延迟加载"><a href="#1-设置延迟加载" class="headerlink" title="1. 设置延迟加载"></a>1. 设置延迟加载</h4><blockquote>
<p><code>MyBatis</code> 默认是关闭延迟加载的,需要在配置文件中的<settings>标签中手动开启。</p>
</blockquote>
<table>
<thead>
<tr>
<th>settings</th>
<th>description</th>
<th>验证值组</th>
<th>默认值</th>
</tr>
</thead>
<tbody><tr>
<td>lazyLoadingEnabled</td>
<td>全局性设置懒加载。</td>
<td>true</td>
<td>false</td>
</tr>
<tr>
<td>aggressiveLazyLoading</td>
<td>积极性的懒加载,false则是按需加载</td>
<td>true</td>
<td>false</td>
</tr>
</tbody></table>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;settings&gt;</span><br><span class="line">	&lt;!-- 开启延迟加载 ,默认值true--&gt;</span><br><span class="line">	&lt;setting name=<span class="string">&quot;lazyLoadingEnabled&quot;</span> value=<span class="string">&quot;true&quot;</span>/&gt;</span><br><span class="line">	&lt;!-- 设置积极的懒加载,默认值true --&gt;</span><br><span class="line">	&lt;setting name=<span class="string">&quot;aggressiveLazyLoading&quot;</span> value=<span class="string">&quot;false&quot;</span>/&gt;</span><br><span class="line">&lt;/settings&gt;</span><br></pre></td></tr></table></figure>
<h4 id="2-在association中使用延迟加载"><a href="#2-在association中使用延迟加载" class="headerlink" title="2. 在association中使用延迟加载"></a>2. 在association中使用延迟加载</h4><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 查询订单 并延迟加载用户信息 --&gt;</span><br><span class="line">	&lt;select id=<span class="string">&quot;selectOrdersAndLazyLoadingUser&quot;</span> resultMap=<span class="string">&quot;selectOrdersAndLazyLoadingUserRetMap&quot;</span>&gt;</span><br><span class="line">		SELECT * FROM orders</span><br><span class="line">	&lt;/select&gt;</span><br><span class="line">	</span><br><span class="line">	&lt;!-- selectOrdersAndLazyLoadingUserRetMap --&gt;</span><br><span class="line">	&lt;resultMap type=<span class="string">&quot;orders&quot;</span> id=<span class="string">&quot;selectOrdersAndLazyLoadingUserRetMap&quot;</span>&gt;</span><br><span class="line">		&lt;id column=<span class="string">&quot;id&quot;</span> property=<span class="string">&quot;id&quot;</span>/&gt;</span><br><span class="line">		&lt;result column=<span class="string">&quot;user_id&quot;</span> property=<span class="string">&quot;userId&quot;</span>/&gt;</span><br><span class="line">		&lt;result column=<span class="string">&quot;number&quot;</span> property=<span class="string">&quot;number&quot;</span>/&gt;</span><br><span class="line">		&lt;result column=<span class="string">&quot;createtime&quot;</span> property=<span class="string">&quot;createtime&quot;</span>/&gt;</span><br><span class="line">		&lt;result column=<span class="string">&quot;note&quot;</span> property=<span class="string">&quot;note&quot;</span>/&gt;</span><br><span class="line">		&lt;!-- 一对一关联并延迟加载用户信息</span><br><span class="line">			select:指定延迟加载执行的statementId</span><br><span class="line">			(如果这个statement不在当前namespace中那么则需要使用namespace.statementid)</span><br><span class="line">			column:需要关联查询的列，如果需要传入多个则需要使用 &#123;user_id=id,...&#125;的格式</span><br><span class="line">		 --&gt;</span><br><span class="line">		&lt;association property=<span class="string">&quot;user&quot;</span> column=<span class="string">&quot;user_id&quot;</span> </span><br><span class="line">			select=<span class="string">&quot;com.sun.test.mapper.UserMapper.findById&quot;</span>&gt;&lt;/association&gt;</span><br><span class="line">	&lt;/resultMap&gt;</span><br></pre></td></tr></table></figure>
<h3 id="查询缓存"><a href="#查询缓存" class="headerlink" title="查询缓存"></a>查询缓存</h3><h4 id="1-一级缓存"><a href="#1-一级缓存" class="headerlink" title="1. 一级缓存"></a>1. 一级缓存</h4><blockquote>
<p>一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象，在对象中有一个数据结构（HashMap）用于存储缓存数据。不同的sqlSession之间的缓存数据区域（HashMap）是互相不影响的。</p>
</blockquote>
<p><img src="http://ww3.sinaimg.cn/mw690/63503acbjw1f4u0a7gs9tj20d709ot8z.jpg"></p>
<blockquote>
<p>当第一次查询对象1时,将先会去一级缓存中查找是否有对象1的数据信息,如果没有则从数据库中查询到数据信息并构造一个key存储到一级缓存(HashMap)中。<br>当第二次查询对象1的时候，则可以凭借key在一级缓存中找到数据信息,而不用再去访问数据库。<br>如果SqlSession进行了事务提交(commit),则会刷新(清空)缓存,目的是为了让缓存存储最新的数据,防止脏读。<br><code>MyBatis</code>默认开启一级缓存。</p>
</blockquote>
<h4 id="2-二级缓存"><a href="#2-二级缓存" class="headerlink" title="2. 二级缓存"></a>2. 二级缓存</h4><blockquote>
<p>二级缓存是<strong>namespace</strong>(mapper)级别的缓存，多个SqlSession去操作同一个<strong>namespace</strong>中的mapper的sql语句，多个SqlSession可以共用二级缓存，二级缓存是跨SqlSession的。<br>二级缓存存储数据不一定是在内存中,所以需要给缓存的对象实现序列化接口。<br>二级缓存需要手动设置开启。</p>
</blockquote>
<h5 id="开启二级缓存"><a href="#开启二级缓存" class="headerlink" title="开启二级缓存"></a>开启二级缓存</h5><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">   在settings中设置</span><br><span class="line">&lt;!-- 开启二级缓存 --&gt;</span><br><span class="line">&lt;setting name=<span class="string">&quot;cacheEnabled&quot;</span> value=<span class="string">&quot;true&quot;</span>/&gt;</span><br><span class="line"></span><br><span class="line">在mapper映射文件中设置</span><br><span class="line">&lt;!-- 使用第三方(ehcache)二级缓存</span><br><span class="line">     flashInterval:设置定时刷新的间隔时间,单位是毫秒。</span><br><span class="line">     注:使用第三方缓存框架需要先导入jar包和整合包</span><br><span class="line">--&gt;</span><br><span class="line">   &lt;cache type=<span class="string">&quot;org.mybatis.caches.ehcache.EhcacheCache&quot;</span> flashInterval=<span class="string">&quot;60000&quot;</span> /&gt;</span><br></pre></td></tr></table></figure>
<h3 id="MyBatis与Spring整合"><a href="#MyBatis与Spring整合" class="headerlink" title="MyBatis与Spring整合"></a>MyBatis与Spring整合</h3><blockquote>
<p>由<code>Spring</code>维护管理数据源、事务、SqlSessionFactory、mapper。<br><code>MyBatis</code>的配置文件只需要配置settings、别名等即可。</p>
</blockquote>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">Spring中的配置</span><br><span class="line">&lt;bean id=<span class="string">&quot;sqlSessionFactory&quot;</span> class=<span class="string">&quot;org.mybatis.spring.SqlSessionFactoryBean&quot;</span>&gt;</span><br><span class="line">	&lt;!-- mybatis的配置文件路径 --&gt;</span><br><span class="line">	&lt;property name=<span class="string">&quot;configLocation&quot;</span> value=<span class="string">&quot;sqlMapConfig.xml&quot;</span>&gt;&lt;/property&gt;</span><br><span class="line">	&lt;!-- 注入数据源 --&gt;</span><br><span class="line">	&lt;property name=<span class="string">&quot;dataSource&quot;</span> ref=<span class="string">&quot;dataSource&quot;</span>&gt;&lt;/property&gt;</span><br><span class="line">&lt;/bean&gt;</span><br><span class="line"></span><br><span class="line">批量生成Mapper(生成的Mapper名字默认为首字母)</span><br><span class="line">&lt;bean class=<span class="string">&quot;org.mybatis.spring.mapper.MapperScannerConfigurer&quot;</span>&gt;</span><br><span class="line">	&lt;!-- 指定需要扫描的mapper配置的包名 --&gt;</span><br><span class="line">	&lt;property name=<span class="string">&quot;basePackage&quot;</span> value=<span class="string">&quot;com.sun.test.mapper&quot;</span>&gt;&lt;/property&gt;</span><br><span class="line">	&lt;!-- 注入SqlSessionFactory --&gt;</span><br><span class="line">	&lt;property name=<span class="string">&quot;sqlSessionFactoryBeanName&quot;</span> value=<span class="string">&quot;sqlSessionFactory&quot;</span>&gt;&lt;/property&gt;</span><br><span class="line">&lt;/bean&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh">
    <link itemprop="mainEntityOfPage" href="https://suyuhuan.gitee.io/yuwanzi.io/2016/06/11/2016-06-11-MyBatis-XML%E9%85%8D%E7%BD%AE%E4%B8%8E%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/yuwanzi.io/images/avatar.gif">
      <meta itemprop="name" content="玉丸子">
      <meta itemprop="description" content="这里是玉丸子的个人博客,与你一起发现更大的世界。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="玉丸子 | Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/yuwanzi.io/2016/06/11/2016-06-11-MyBatis-XML%E9%85%8D%E7%BD%AE%E4%B8%8E%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6/" class="post-title-link" itemprop="url">MyBatis-XML配置与映射文件</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Veröffentlicht am</span>

      <time title="Erstellt: 2016-06-11 00:00:00" itemprop="dateCreated datePublished" datetime="2016-06-11T00:00:00+08:00">2016-06-11</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">Bearbeitet am</span>
        <time title="Geändert am: 2020-11-07 08:58:17" itemprop="dateModified" datetime="2020-11-07T08:58:17+08:00">2020-11-07</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">in</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">后端</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Java/MyBatis/" itemprop="url" rel="index"><span itemprop="name">MyBatis</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <p><img src="http://ww3.sinaimg.cn/mw690/63503acbjw1f4pf96s0tcj209302caa2.jpg" alt="MyBatis"></p>
<h2 id="全局XML配置文件"><a href="#全局XML配置文件" class="headerlink" title="全局XML配置文件"></a>全局XML配置文件</h2><p><code>MyBatis</code>配置文件的结构如下：</p>
<ul>
<li>configuration 配置<ul>
<li>properties 属性</li>
<li>settings 参数设置</li>
<li>typeAliases 类型别名</li>
<li>typeHandlers 类型处理器</li>
<li>objectFactory 对象工厂</li>
<li>plugins 插件</li>
<li>environments 环境集合<ul>
<li>environment 环境<ul>
<li>transactionManager 事务管理器</li>
<li>dataSource 数据源</li>
</ul>
</li>
<li>databaseIdProvider 数据库厂商标识</li>
<li>mappers 映射器</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="常用标签配置"><a href="#常用标签配置" class="headerlink" title="常用标签配置"></a>常用标签配置</h3><h4 id="1-properties"><a href="#1-properties" class="headerlink" title="1. properties"></a>1. <strong>properties</strong></h4><pre><code>properties标签可以读取properties配置文件,并引入到 MyBatis 的配置文件中。
可以通过子标签定义key/value。</code></pre>
<p>例如：</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;properties resource=<span class="string">&quot;com/sun/test/dataSource.properties&quot;</span>&gt;</span><br><span class="line">    &lt;property name=<span class="string">&quot;username&quot;</span> value=<span class="string">&quot;dev_user&quot;</span>/&gt;</span><br><span class="line">    &lt;property name=<span class="string">&quot;password&quot;</span> value=<span class="string">&quot;F2Fa3!33TYyg&quot;</span>/&gt;</span><br><span class="line">&lt;/properties&gt;</span><br></pre></td></tr></table></figure>
<p> 其中的属性就可以在整个配置文件中使用key来替换需要动态配置的属性值。</p>
<p>例如：</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;dataSource type=<span class="string">&quot;POOLED&quot;</span>&gt;</span><br><span class="line">  &lt;property name=<span class="string">&quot;driver&quot;</span> value=<span class="string">&quot;$&#123;driver&#125;&quot;</span>/&gt;</span><br><span class="line">  &lt;property name=<span class="string">&quot;url&quot;</span> value=<span class="string">&quot;$&#123;url&#125;&quot;</span>/&gt;</span><br><span class="line">  &lt;property name=<span class="string">&quot;username&quot;</span> value=<span class="string">&quot;$&#123;username&#125;&quot;</span>/&gt;</span><br><span class="line">  &lt;property name=<span class="string">&quot;password&quot;</span> value=<span class="string">&quot;$&#123;password&#125;&quot;</span>/&gt;</span><br><span class="line">&lt;/dataSource&gt;</span><br></pre></td></tr></table></figure>

<p>properties的加载顺序</p>
<ul>
<li>最先加载properties中的子标签所定义的属性。</li>
<li>然后会加载resource标签所引入的properties配置文件中的属性,并覆盖已加载的同名属性。</li>
<li>最后加载作为方法参数(parameterType中的key/value)传递的属性，并覆盖已加载的同名属性。</li>
</ul>
<p>总结：</p>
<ul>
<li>通过方法参数传递的属性具有最高优先级。</li>
<li>resource引用的配置文件中的属性次之。</li>
<li>最低优先级的是 properties 子标签中指定的属性。</li>
</ul>
<h4 id="2-settings"><a href="#2-settings" class="headerlink" title="2. settings"></a>2. <strong>settings</strong></h4><pre><code>settings会影响MyBatis的运行行为。</code></pre>
<p>一个配置完整的 settings 的示例如下：</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&lt;settings&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;cacheEnabled&quot;</span> value=<span class="string">&quot;true&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;lazyLoadingEnabled&quot;</span> value=<span class="string">&quot;true&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;multipleResultSetsEnabled&quot;</span> value=<span class="string">&quot;true&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;useColumnLabel&quot;</span> value=<span class="string">&quot;true&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;useGeneratedKeys&quot;</span> value=<span class="string">&quot;false&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;autoMappingBehavior&quot;</span> value=<span class="string">&quot;PARTIAL&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;autoMappingUnknownColumnBehavior&quot;</span> value=<span class="string">&quot;WARNING&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;defaultExecutorType&quot;</span> value=<span class="string">&quot;SIMPLE&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;defaultStatementTimeout&quot;</span> value=<span class="string">&quot;25&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;defaultFetchSize&quot;</span> value=<span class="string">&quot;100&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;safeRowBoundsEnabled&quot;</span> value=<span class="string">&quot;false&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;mapUnderscoreToCamelCase&quot;</span> value=<span class="string">&quot;false&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;localCacheScope&quot;</span> value=<span class="string">&quot;SESSION&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;jdbcTypeForNull&quot;</span> value=<span class="string">&quot;OTHER&quot;</span>/&gt;</span><br><span class="line">  &lt;setting name=<span class="string">&quot;lazyLoadTriggerMethods&quot;</span> value=<span class="string">&quot;equals,clone,hashCode,toString&quot;</span>/&gt;</span><br><span class="line">&lt;/settings&gt;</span><br></pre></td></tr></table></figure>
<h4 id="3-typeAliases"><a href="#3-typeAliases" class="headerlink" title="3. typeAliases"></a>3. <strong>typeAliases</strong></h4><p>类型别名,可以对JavaBean设置一个别名,用来减少完全限定名的冗余。<br>例如：</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 类型别名 --&gt;</span><br><span class="line">	&lt;typeAliases&gt;</span><br><span class="line">		&lt;!-- 设置单个别名 --&gt;</span><br><span class="line">		&lt;typeAlias type=<span class="string">&quot;com.sun.test.entity.User&quot;</span> alias=<span class="string">&quot;user&quot;</span>/&gt;</span><br><span class="line">		&lt;!-- package指定一个包名,会在包下搜索需要的JavaBean</span><br><span class="line">			   如果没有注解,则默认设置为JavaBean的首字母小写的非限定类名作为它的别名。</span><br><span class="line">			   如果有@Alias注解,则使用其注解值作为它的别名。</span><br><span class="line">		 --&gt;</span><br><span class="line">		 &lt;package name=<span class="string">&quot;com.sun.test.entity&quot;</span>/&gt;</span><br><span class="line">	&lt;/typeAliases&gt;</span><br></pre></td></tr></table></figure>
<p><code>MyBatis</code>默认支持的类型别名如下,它们都是大小写不敏感的，需要注意的是由基本类型名称重复导致的特殊处理。</p>
<table>
<thead>
<tr>
<th>别名</th>
<th>映射的类型</th>
</tr>
</thead>
<tbody><tr>
<td>_byte</td>
<td>byte</td>
</tr>
<tr>
<td>_long</td>
<td>long</td>
</tr>
<tr>
<td>_short</td>
<td>short</td>
</tr>
<tr>
<td>_int</td>
<td>int</td>
</tr>
<tr>
<td>_integer</td>
<td>int</td>
</tr>
<tr>
<td>_double</td>
<td>double</td>
</tr>
<tr>
<td>_float</td>
<td>float</td>
</tr>
<tr>
<td>_boolean</td>
<td>boolean</td>
</tr>
<tr>
<td>string</td>
<td>String</td>
</tr>
<tr>
<td>byte</td>
<td>Byte</td>
</tr>
<tr>
<td>long</td>
<td>Long</td>
</tr>
<tr>
<td>short</td>
<td>Short</td>
</tr>
<tr>
<td>int</td>
<td>Integer</td>
</tr>
<tr>
<td>integer</td>
<td>Integer</td>
</tr>
<tr>
<td>double</td>
<td>Double</td>
</tr>
<tr>
<td>float</td>
<td>Float</td>
</tr>
<tr>
<td>boolean</td>
<td>Boolean</td>
</tr>
<tr>
<td>date</td>
<td>Date</td>
</tr>
<tr>
<td>decimal</td>
<td>BigDecimal</td>
</tr>
<tr>
<td>bigdecimal</td>
<td>BigDecimal</td>
</tr>
<tr>
<td>object</td>
<td>Object</td>
</tr>
<tr>
<td>map</td>
<td>Map</td>
</tr>
<tr>
<td>hashmap</td>
<td>HashMap</td>
</tr>
<tr>
<td>list</td>
<td>List</td>
</tr>
<tr>
<td>arraylist</td>
<td>ArrayList</td>
</tr>
<tr>
<td>collection</td>
<td>Collection</td>
</tr>
<tr>
<td>iterator</td>
<td>Iterator</td>
</tr>
</tbody></table>
<h4 id="4-Mappers"><a href="#4-Mappers" class="headerlink" title="4. Mappers"></a>4. <strong>Mappers</strong></h4><p>映射器(Mappers)用于引入Mapper映射文件。</p>
<p>使用相对路径的方式引入</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 相对路径 --&gt;</span><br><span class="line">&lt;mappers&gt;</span><br><span class="line">  &lt;mapper resource=<span class="string">&quot;com/sun/test/mapper/UserMapper.xml&quot;</span>/&gt;</span><br><span class="line">&lt;/mappers&gt;</span><br></pre></td></tr></table></figure>
<p>使用绝对路径的方式引入</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 绝对路径s --&gt;</span><br><span class="line">&lt;mappers&gt;</span><br><span class="line">  &lt;mapper url=<span class="string">&quot;file:///D:\sun\mappers\UserMapper.xml&quot;</span>/&gt;</span><br><span class="line">&lt;/mappers&gt;</span><br></pre></td></tr></table></figure>
<p>使用Mapper接口的全限定类名(需要mapper接口与mapper映射文件名称相同,并且在同一个包下)</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- Mapper接口的全限定类名 --&gt;</span><br><span class="line">&lt;mappers&gt;</span><br><span class="line">  &lt;mapper class=<span class="string">&quot;com.sun.test.mapper.UserMapper&quot;</span>/&gt;</span><br><span class="line">&lt;/mappers&gt;</span><br></pre></td></tr></table></figure>
<p>扫描指定包下的所有映射文件(需要mapper接口与mapper映射文件名称相同,并且在同一个包下)</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 扫描指定包下的所有映射文件 --&gt;</span><br><span class="line">&lt;mappers&gt;</span><br><span class="line">  &lt;package name=<span class="string">&quot;com.sun.test.mapper&quot;</span>/&gt;</span><br><span class="line">&lt;/mappers&gt;</span><br></pre></td></tr></table></figure>

<hr>
<h2 id="Mapper映射文件"><a href="#Mapper映射文件" class="headerlink" title="Mapper映射文件"></a>Mapper映射文件</h2><ul>
<li><code>cache</code> 缓存配置</li>
<li><code>cache-ref</code> 其他namespace缓存配置的引用</li>
<li><code>resultType</code> 结果集映射的类型</li>
<li><code>resultMap</code> 结果集映射Map</li>
<li><code>parameterType</code> 输入映射类型</li>
<li><code>sql</code> 可被引用的复用sql语句块</li>
<li><code>insert</code> 映射插入语句</li>
<li><code>update</code> 映射更新语句</li>
<li><code>select</code> 映射查询语句</li>
<li><code>delete</code> 映射删除语句</li>
</ul>
<h3 id="resultType"><a href="#resultType" class="headerlink" title="resultType"></a>resultType</h3><p>注意事项:</p>
<ol>
<li>如果使用resultType进行结果集映射,则需要查询出的列名与映射的JavaBean属性名称一致。</li>
<li>SQL语句中列名如果有别名,则列名为别名的名称。</li>
<li>如果查询的列名和JavaBean所映射的属性名全不一致,则映射的JavaBean对象为null。</li>
<li>如果查询的列名和JavaBean所映射的属性名少数不一致,则映射的JavaBean对象不为null,但只有名称一致的属性有值。</li>
</ol>
<p>例如：</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">   &lt;!-- 根据id查询User --&gt;</span><br><span class="line">&lt;select id=<span class="string">&quot;findById&quot;</span> parameterType=<span class="string">&quot;int&quot;</span> resultType=<span class="string">&quot;com.sun.test.entity.User&quot;</span>&gt;</span><br><span class="line">	select * from user where id = #&#123;id&#125;</span><br><span class="line">&lt;/select&gt;</span><br></pre></td></tr></table></figure>
<h3 id="resultMap"><a href="#resultMap" class="headerlink" title="resultMap"></a>resultMap</h3><p>注意事项:</p>
<ol>
<li>使用resultMap进行结果集映射,不需要列名与映射的JavaBean属性名称一致。</li>
<li>使用resultMap进行结果集映射,需要先定义一个resultMap。</li>
</ol>
<p>例如:</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 定义一个resultMap --&gt;</span><br><span class="line">&lt;resultMap type=<span class="string">&quot;com.sun.test.entity.User&quot;</span> id=<span class="string">&quot;userResultMap&quot;</span>&gt;</span><br><span class="line">	&lt;!-- 主键 --&gt;</span><br><span class="line">	&lt;id column=<span class="string">&quot;id&quot;</span> property=<span class="string">&quot;id&quot;</span>/&gt;</span><br><span class="line">	&lt;!-- 其他字段 --&gt;</span><br><span class="line">	&lt;result column=<span class="string">&quot;username&quot;</span> property=<span class="string">&quot;username&quot;</span>/&gt;</span><br><span class="line">&lt;/resultMap&gt;</span><br><span class="line">&lt;select id=<span class="string">&quot;findByIdWithRetMap&quot;</span> parameterType=<span class="string">&quot;int&quot;</span> resultMap=<span class="string">&quot;userResultMap&quot;</span>&gt;</span><br><span class="line">	select id,username from user where id = #&#123;id&#125;</span><br><span class="line">&lt;/select&gt;</span><br></pre></td></tr></table></figure>
<h3 id="动态SQL"><a href="#动态SQL" class="headerlink" title="动态SQL"></a>动态SQL</h3><h4 id="1-SQL片段"><a href="#1-SQL片段" class="headerlink" title="1. SQL片段"></a>1. SQL片段</h4><p>sql片段可以存储动态的sql语句,提高复用性。</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- SQL片段,可以存储动态的SQL语句 --&gt;</span><br><span class="line">	&lt;sql id=<span class="string">&quot;sql&quot;</span>&gt;</span><br><span class="line">		&lt;!-- 判断用户名不为空 --&gt;</span><br><span class="line">		&lt;<span class="keyword">if</span> test=<span class="string">&quot;username != null and username != &#x27;&#x27;&quot;</span>&gt;</span><br><span class="line">			and username = #&#123;usernmae&#125;</span><br><span class="line">		&lt;/<span class="keyword">if</span>&gt;</span><br><span class="line">		&lt;!-- 判断性别不为空 --&gt;</span><br><span class="line">		&lt;<span class="keyword">if</span> test=<span class="string">&quot;sex != null and sex != &#x27;&#x27;&quot;</span>&gt;</span><br><span class="line">			and sex = #&#123;sex&#125;</span><br><span class="line">		&lt;/<span class="keyword">if</span>&gt;</span><br><span class="line">	&lt;/sql&gt;</span><br></pre></td></tr></table></figure>
<h4 id="2-if标签"><a href="#2-if标签" class="headerlink" title="2. if标签"></a>2. if标签</h4><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;select id=<span class="string">&quot;findByIdOrLikeName&quot;</span> resultType=<span class="string">&quot;com.sun.test.entity.User&quot;</span>&gt;</span><br><span class="line">  select * from user where id = #&#123;id&#125;</span><br><span class="line">  &lt;!-- 如果<span class="keyword">if</span>返回为true 则会加上这条语句 --&gt;</span><br><span class="line">  &lt;<span class="keyword">if</span> test=<span class="string">&quot;username != null and username != &#x27;&#x27;&quot;</span>&gt;</span><br><span class="line">    and username like <span class="string">&#x27;%$&#123;username&#125;%&#x27;</span></span><br><span class="line">  &lt;/<span class="keyword">if</span>&gt;</span><br><span class="line">&lt;/select&gt;</span><br></pre></td></tr></table></figure>
<h4 id="3-where标签"><a href="#3-where标签" class="headerlink" title="3. where标签"></a>3. where标签</h4><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;select id=<span class="string">&quot;findAllOrLikeName&quot;</span> resultType=<span class="string">&quot;com.sun.test.entity.User&quot;</span>&gt;</span><br><span class="line">  select * from user</span><br><span class="line">  &lt;!-- where标签只有在<span class="keyword">if</span>为true的情况下才会添加where语句</span><br><span class="line">       并且会将第一条语句的and去掉。</span><br><span class="line">  --&gt;</span><br><span class="line">  &lt;where&gt;</span><br><span class="line">    &lt;<span class="keyword">if</span> test=<span class="string">&quot;username != null and username != &#x27;&#x27;&quot;</span>&gt;</span><br><span class="line">        and username like <span class="string">&#x27;%$&#123;username&#125;%&#x27;</span></span><br><span class="line">     &lt;/<span class="keyword">if</span>&gt;</span><br><span class="line">  &lt;/where&gt;</span><br><span class="line">&lt;/select&gt;</span><br></pre></td></tr></table></figure>
<h4 id="4-foreach标签"><a href="#4-foreach标签" class="headerlink" title="4. foreach标签"></a>4. foreach标签</h4><p>foreach标签可以对一个集合进行遍历,通常是在构建一个in条件语句的时候使用。</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&lt;select id=<span class="string">&quot;selectUserIn&quot;</span> resultType=<span class="string">&quot;com.sun.test.entity.User&quot;</span>  parameterType=<span class="string">&quot;list&quot;</span>&gt;</span><br><span class="line">	select * from user</span><br><span class="line">	&lt;where&gt;</span><br><span class="line">		&lt;<span class="keyword">if</span> test=<span class="string">&quot;list != null and list.size &gt; 0&quot;</span>&gt;</span><br><span class="line">			&lt;!-- </span><br><span class="line">				collection：集合参数的名称。</span><br><span class="line">				item：遍历集合时的值</span><br><span class="line">				open：遍历开始时需要拼接的sql语句</span><br><span class="line">				close：遍历结束时需要拼接的sql语句</span><br><span class="line">				separator：遍历过程中需要拼接的字符串</span><br><span class="line">			 --&gt;</span><br><span class="line">			&lt;foreach collection=<span class="string">&quot;list&quot;</span> item=<span class="string">&quot;id&quot;</span> open=<span class="string">&quot;and id in(&quot;</span> close=<span class="string">&quot;)&quot;</span> separator=<span class="string">&quot;,&quot;</span>&gt;</span><br><span class="line">				#&#123;id&#125;</span><br><span class="line">			&lt;/foreach&gt;</span><br><span class="line">		&lt;/<span class="keyword">if</span>&gt;</span><br><span class="line">	&lt;/where&gt;</span><br><span class="line">&lt;/select&gt;</span><br></pre></td></tr></table></figure>
<h4 id="5-bind标签"><a href="#5-bind标签" class="headerlink" title="5. bind标签"></a>5. bind标签</h4><p>bind标签可以从OGNL表达式中创建一个变量并将其绑定到上下文。</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;select id=<span class="string">&quot;selectUserLikeName&quot;</span> resultType=<span class="string">&quot;com.sun.test.entity.User&quot;</span>&gt;</span><br><span class="line">  &lt;bind name=<span class="string">&quot;username&quot;</span> value=<span class="string">&quot;&#x27;%&#x27; + user.getUsername() + &#x27;%&#x27;&quot;</span> /&gt;</span><br><span class="line">  select * from user</span><br><span class="line">  where username like #&#123;username&#125;</span><br><span class="line">&lt;/select&gt;</span><br></pre></td></tr></table></figure>
      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh">
    <link itemprop="mainEntityOfPage" href="https://suyuhuan.gitee.io/yuwanzi.io/2016/06/10/2016-06-10-mybatis-study%20notes01/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/yuwanzi.io/images/avatar.gif">
      <meta itemprop="name" content="玉丸子">
      <meta itemprop="description" content="这里是玉丸子的个人博客,与你一起发现更大的世界。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="玉丸子 | Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/yuwanzi.io/2016/06/10/2016-06-10-mybatis-study%20notes01/" class="post-title-link" itemprop="url">MyBatis学习笔记-01</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Veröffentlicht am</span>

      <time title="Erstellt: 2016-06-10 00:00:00" itemprop="dateCreated datePublished" datetime="2016-06-10T00:00:00+08:00">2016-06-10</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">Bearbeitet am</span>
        <time title="Geändert am: 2020-11-07 08:58:17" itemprop="dateModified" datetime="2020-11-07T08:58:17+08:00">2020-11-07</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">in</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">后端</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
        </span>
          . 
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/yuwanzi.io/categories/%E5%90%8E%E7%AB%AF/Java/MyBatis/" itemprop="url" rel="index"><span itemprop="name">MyBatis</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <p><img src="http://ww3.sinaimg.cn/mw690/63503acbjw1f4pf96s0tcj209302caa2.jpg" alt="MyBatis"></p>
<h3 id="1-什么是MyBatis"><a href="#1-什么是MyBatis" class="headerlink" title="1.什么是MyBatis?"></a>1.什么是MyBatis?</h3><ul>
<li>MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code，并且改名为MyBatis 。2013年11月迁移到Github。</li>
<li>iBATIS一词来源于“internet”和“abatis”的组合，是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects（DAO）</li>
<li>MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。</li>
<li>MyBatis 可以对配置和原生Map使用简单的 XML 或注解，将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。</li>
</ul>
<h3 id="2-MyBatis框架原理"><a href="#2-MyBatis框架原理" class="headerlink" title="2.MyBatis框架原理"></a>2.MyBatis框架原理</h3><h4 id="MyBatis的功能架构分为三层"><a href="#MyBatis的功能架构分为三层" class="headerlink" title="MyBatis的功能架构分为三层"></a>MyBatis的功能架构分为三层</h4><ol>
<li>API接口层：提供给外部使用的接口API，开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。  </li>
<li>数据处理层：负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。  </li>
<li>基础支撑层：负责最基础的功能支撑，包括连接管理、事务管理、配置加载和缓存处理，这些都是共用的东西，将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。<br><img src="http://i4.buimg.com/47c91060a0871659.png"></li>
</ol>
<h4 id="MyBatis框架架构流程"><a href="#MyBatis框架架构流程" class="headerlink" title="MyBatis框架架构流程"></a>MyBatis框架架构流程</h4><p><img src="http://i4.buimg.com/60494497248097cf.png"></p>
<ol>
<li>MyBatis应用程序通过读取XML配置文件,构造出SqlSessionFactory(SQL会话工厂)。</li>
<li>SqlSessionFactory再根据配置,构造一个SqlSession(SQL会话)。MyBatis通过SqlSession完成数据库操作。</li>
<li>SqlSession本身不能直接操作数据库,它是通过底层Executor接口操作数据库的。Executor有2个实现类,默认使用缓存执行器。</li>
<li>Executor将处理的SQL信息封装到一个底层对象 MappedStatement 中。该对象包含了SQL语句、输入参数信息、输出结果集信息。</li>
<li>输入参数和输出结果集的映射类型为java的简单类型、HashMap集合类型、POJO对象类型。</li>
</ol>
<h3 id="3-MyBatis的优点与缺点"><a href="#3-MyBatis的优点与缺点" class="headerlink" title="3.MyBatis的优点与缺点"></a>3.MyBatis的优点与缺点</h3><p>优点</p>
<ul>
<li>学习成本低、简单易学。</li>
<li>灵活性较高,可以直接对SQL进行性能优化。</li>
<li>SQL与业务逻辑代码低耦合,提高了维护性。</li>
<li>可以编写动态SQL语句。</li>
</ul>
<p>缺点</p>
<ul>
<li>SQL语句依赖数据库,即数据库发生变更时,需要重新写SQL语句, 移植性较差。</li>
<li>SQL语句繁多,工作量大。</li>
<li>二级缓存机制不佳。</li>
</ul>
<h3 id="4-MyBatis入门"><a href="#4-MyBatis入门" class="headerlink" title="4.MyBatis入门"></a>4.MyBatis入门</h3><p>我们使用MyBatis完成一个根据id查询用户的需求。</p>
<p><strong>创建一个JavaBean</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">public class User &#123;</span><br><span class="line"></span><br><span class="line">     private int id ;</span><br><span class="line">     private String username ;&#x2F;&#x2F; 姓名</span><br><span class="line">     private String sex ;&#x2F;&#x2F; 性别</span><br><span class="line">     private Date birthday ;&#x2F;&#x2F; 生日</span><br><span class="line">     private String address ;&#x2F;&#x2F; 地址</span><br></pre></td></tr></table></figure>
<p><strong>为User类配置一个映射文件</strong></p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;? xml version =<span class="string">&quot;1.0&quot;</span> encoding= <span class="string">&quot;UTF-8&quot;</span> ?&gt;</span><br><span class="line">&lt;! DOCTYPE mapper</span><br><span class="line">PUBLIC <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span><br><span class="line"><span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span> &gt;</span><br><span class="line">&lt; mapper namespace =<span class="string">&quot;com.sun.test.mapper.UserMapper&quot;</span> &gt;</span><br><span class="line">     &lt;!-- 根据id查询User</span><br><span class="line">          在命名空间 com.sun.test.mapper.UserMapper中定义了一个id为findById的映射语句。</span><br><span class="line">          当我们调用时可以使用 namespace.id 来进行调用。</span><br><span class="line">          即：com.sun.test.mapper.UserMapper.findById </span><br><span class="line">     --&gt;</span><br><span class="line">     &lt;select id= <span class="string">&quot;findById&quot;</span> parameterType =<span class="string">&quot;int&quot;</span> resultType =<span class="string">&quot;com.sun.test.entity.User&quot;</span> &gt;</span><br><span class="line">         select * from user where id = #&#123;id&#125;</span><br><span class="line">     &lt;/select &gt;</span><br><span class="line">&lt;/ mapper&gt;</span><br></pre></td></tr></table></figure>
<ul>
<li>命名空间(Namespace): 必须且非常重要,最好使用对应mapper接口的全限定名(比如:com.sun.test.mapper.UserMapper )。</li>
<li>parameterType: 输入参数的类型,可以使用类型的全限定名或者别名。</li>
<li>resultType: 返回参数的类型,如果是集合类型,则应使用集合内可以包含的类型,而不能是集合本身,可以使用类型的全限定名或者别名。</li>
</ul>
<p><strong>创建一个全局配置文件,并配置数据源、事务管理器、映射文件等基本配置。</strong>    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&lt;? xml version &#x3D;&quot;1.0&quot; encoding&#x3D; &quot;UTF-8&quot; ?&gt;</span><br><span class="line">&lt;! DOCTYPE configuration</span><br><span class="line">  PUBLIC &quot;-&#x2F;&#x2F;mybatis.org&#x2F;&#x2F;DTD Config 3.0&#x2F;&#x2F;EN&quot;</span><br><span class="line">  &quot;http:&#x2F;&#x2F;mybatis.org&#x2F;dtd&#x2F;mybatis-3-config.dtd&quot; &gt;</span><br><span class="line">&lt; configuration&gt;</span><br><span class="line">     &lt;environments default&#x3D; &quot;development&quot;&gt;</span><br><span class="line">          &lt; environment id&#x3D; &quot;development&quot; &gt;</span><br><span class="line">              &lt;!-- 配置事务管理器 --&gt;</span><br><span class="line">              &lt; transactionManager type &#x3D;&quot;JDBC&quot; &#x2F;&gt;</span><br><span class="line">              &lt;!-- 配置数据源 --&gt;</span><br><span class="line">              &lt; dataSource type &#x3D;&quot;POOLED&quot; &gt;</span><br><span class="line">                  &lt; property name &#x3D;&quot;driver&quot; value &#x3D;&quot;com.mysql.jdbc.Driver&quot; &#x2F;&gt;</span><br><span class="line">                  &lt; property name &#x3D;&quot;url&quot; value &#x3D;&quot;jdbc:mysql:&#x2F;&#x2F;&#x2F;mybatis&quot; &#x2F;&gt;</span><br><span class="line">                  &lt; property name &#x3D;&quot;username&quot; value &#x3D;&quot;root&quot; &#x2F;&gt;</span><br><span class="line">                  &lt; property name &#x3D;&quot;password&quot; value &#x3D;&quot;root&quot; &#x2F;&gt;</span><br><span class="line">              &lt;&#x2F; dataSource&gt;</span><br><span class="line">          &lt;&#x2F; environment&gt;</span><br><span class="line">     &lt;&#x2F;environments &gt;</span><br><span class="line">     &lt;!-- 配置映射文件 --&gt;</span><br><span class="line">     &lt;mappers &gt;</span><br><span class="line">          &lt;!-- 使用package可以查找到所有 mapper接口与 mapper映射文件但需要同名并且放在同一包下 --&gt;</span><br><span class="line">          &lt; package name &#x3D;&quot;com.sun.test.mapper&quot; &#x2F;&gt;</span><br><span class="line">     &lt;&#x2F;mappers &gt;</span><br><span class="line">&lt;&#x2F; configuration&gt;</span><br></pre></td></tr></table></figure>
<p><strong>测试</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test01</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">         <span class="comment">// 获得配置文件的资源流</span></span><br><span class="line">        InputStream inputStream = Resources.getResourceAsStream( <span class="string">&quot;sqlMapConfig.xml&quot;</span>);</span><br><span class="line">         <span class="comment">// 加载配置文件,构造SqlSessionFactory</span></span><br><span class="line">        SqlSessionFactory sqlSessionFactory = <span class="keyword">new</span> SqlSessionFactoryBuilder().build(inputStream );</span><br><span class="line">         <span class="comment">// 使用SqlSessionFactory构造一个SqlSession</span></span><br><span class="line">        SqlSession sqlSession = sqlSessionFactory .openSession();</span><br><span class="line">         <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 执行statement</span></span><br><span class="line"><span class="comment">         * 参数1：statement的id 建议使用 namespace.statementId</span></span><br><span class="line"><span class="comment">         * 参数2：输入参数的值,它的类型要和映射文件中的parameterType类型一致</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        User user = sqlSession .selectOne(<span class="string">&quot;com.sun.test.mapper.UserMapper.findById&quot;</span> , <span class="number">1</span>);</span><br><span class="line">         <span class="comment">// 输出结果</span></span><br><span class="line">        System. out .println(user );</span><br><span class="line">         <span class="comment">// 关闭SqlSession</span></span><br><span class="line">        sqlSession .close();</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>Resources：MyBatis中的一个工具类,可以从classpath或其他位置加载资源文件。</li>
<li>SqlSessionFactoryBuilder： 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。因此 SqlSessionFactoryBuilder 实例的最佳范围是方法范围（也就是局部方法变量）。</li>
<li>SqlSessionFactory：一旦被创建就应该在应用的运行期间一直存在,所以它应该是单例的,且在应用运行期间不要多次创建。</li>
<li>SqlSession：用于操作数据库的对象,每个线程都应该有一个SqlSession实例,它是多例的,并且它是线程不安全的,不能放在全局变量上。</li>
</ul>
<h3 id="5-自增主键"><a href="#5-自增主键" class="headerlink" title="5.自增主键"></a>5.自增主键</h3><p>如果你的数据库支持自动生成主键的字段,那么你可以设置 useGeneratedKeys=”true”,再把keyProperty设置到目标属性上即可。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;insert id&#x3D;&quot;insertUser&quot; useGeneratedKeys&#x3D;&quot;true&quot; parameterType &#x3D;&quot;com.sun.test.entity.User&quot; keyProperty&#x3D;&quot;id&quot;&gt;</span><br><span class="line">     insert into user(username,birthday,sex,address)</span><br><span class="line">     values(#&#123;username&#125;,#&#123;birthday&#125;,#&#123;sex&#125;,#&#123;address&#125;)</span><br><span class="line">&lt;&#x2F;insert&gt;</span><br></pre></td></tr></table></figure>
<p>如果不支持自动生成主键则可以使用另外一种方法生成主键</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt; insert id&#x3D; &quot;insertUser&quot; parameterType &#x3D;&quot;com.sun.test.entity.User&quot; &gt;</span><br><span class="line">          &lt;!-- 返回自增主键</span><br><span class="line">             keyProperty:生成主键的属性</span><br><span class="line">             resultType:生成主键的类型</span><br><span class="line">             order:查询主键SQL的执行顺序,相对于insert,如果设置为 BEFORE，那么它会首先选择主键，设置 keyProperty 然后执行插入语句。</span><br><span class="line">             如果设置为 AFTER，那么会先执行插入语句。</span><br><span class="line">             LAST_INSERT_ID():MySQL的函数,获取最后插入的主键</span><br><span class="line">         --&gt;</span><br><span class="line">          &lt; selectKey keyProperty &#x3D;&quot;id&quot; resultType &#x3D;&quot;int&quot; order&#x3D; &quot;AFTER&quot;&gt;</span><br><span class="line">             select LAST_INSERT_ID()</span><br><span class="line">          &lt;&#x2F; selectKey&gt;</span><br><span class="line">         insert into user(username,birthday,sex,address)</span><br><span class="line">        values(#&#123;username&#125;,#&#123;birthday&#125;,#&#123;sex&#125;,#&#123;address&#125;)</span><br><span class="line">     &lt;&#x2F;insert &gt;</span><br></pre></td></tr></table></figure>
<h4 id="与-的区别"><a href="#与-的区别" class="headerlink" title="#{} 与 ${}的区别"></a>#{} 与 ${}的区别</h4><ol>
<li>#{}可以表示为占位符?,#{id}里面的id表示输入参数的参数名称,如果是简单类型,则名称可以任意填写。</li>
<li>${}表示字符串替换,${value},value表示输入参数的参数名称,如果是简单类型,则名称必须为value。</li>
<li>${}是不安全的,会导致潜在的sql注入攻击,但如果要动态传入order by的列名则必须使用${} 即：order by ${columnName}。</li>
</ol>
<h3 id="6-使用Mapper构建Dao"><a href="#6-使用Mapper构建Dao" class="headerlink" title="6.使用Mapper构建Dao"></a>6.使用Mapper构建Dao</h3><p>使用Mapper构建Dao则只需要开发接口即可。</p>
<h4 id="规范"><a href="#规范" class="headerlink" title="规范"></a>规范</h4><ol>
<li>mapper接口的全限定名称要和mapper映射文件的namespace一致。</li>
<li>mapper接口的方法名称要和mapper映射文件的MappedStatement的id一致。</li>
<li>mapper接口的方法参数类型与返回值类型要和mapper映射文件的MappedStatement的parameterType与resultType一致。</li>
</ol>
<p>例:</p>
<p><img src="http://i4.buimg.com/fb28faf508066198.png" alt="mapper"></p>
<p><img src="http://i4.buimg.com/0382b4a78a6080a2.png" alt="mapper.xml"></p>
<p><img src="http://i4.buimg.com/134368652f63916c.png" alt="test"></p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/yuwanzi.io/page/6/"><i class="fa fa-angle-left" aria-label="Vorherige Seite"></i></a><a class="page-number" href="/yuwanzi.io/">1</a><span class="space">&hellip;</span><a class="page-number" href="/yuwanzi.io/page/6/">6</a><span class="page-number current">7</span>
  </nav>


<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      const activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      const commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>
</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">玉丸子</span>
</div>
  <div class="powered-by">Erstellt mit  <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" class="theme-link" rel="noopener" target="_blank">NexT.Muse</a>
  </div>

    </div>
  </footer>

  
  <script src="//cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script>
<script src="/yuwanzi.io/js/utils.js"></script><script src="/yuwanzi.io/js/motion.js"></script><script src="/yuwanzi.io/js/schemes/muse.js"></script><script src="/yuwanzi.io/js/next-boot.js"></script>

  






  





</body>
</html>
